Problem:
Score : 1100 points

Problem Statement

Snuke got positive integers s_1,...,s_N from his mother, as a birthday present. There may be duplicate elements.

He will circle some of these N integers. Since he dislikes cubic numbers, he wants to ensure that if both s_i and s_j (i ≠ j) are circled, the product s_is_j is not cubic. For example, when s_1=1,s_2=1,s_3=2,s_4=4, it is not possible to circle both s_1 and s_2 at the same time. It is not possible to circle both s_3 and s_4 at the same time, either.

Find the maximum number of integers that Snuke can circle.

Constraints

1 ≦ N ≦ 10^5

1 ≦ s_i ≦ 10^{10}

All input values are integers.

Input

The input is given from Standard Input in the following format:

N
s_1
:
s_N

Output

Print the maximum number of integers that Snuke can circle.

Sample Input 1

8
1
2
3
4
5
6
7
8

Sample Output 1

6

Snuke can circle 1,2,3,5,6,7.

Sample Input 2

6
2
4
8
16
32
64

Sample Output 2

3

Sample Input 3

10
1
10
100
1000000007
10000000000
1000000009
999999999
999
999
999

Sample Output 3

9

Solution in C++14 (GCC 5.4.1) (judge verdict: Wrong Answer)

#pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("Ofast")
//#pragma GCC optimize(3)
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC target("sse3","sse2","sse")
//#pragma GCC target("avx","sse4","sse4.1","sse4.2","ssse3")
//#pragma GCC target("f16c")
//#pragma GCC optimize("inline","fast-math","unroll-loops","no-stack-protector")
//#pragma GCC diagnostic error "-fwhole-program"
//#pragma GCC diagnostic error "-fcse-skip-blocks"
//#pragma GCC diagnostic error "-funsafe-loop-optimizations"
//#pragma GCC diagnostic error "-std=c++14"
#include "bits/stdc++.h"
#include "ext/pb_ds/tree_policy.hpp"
#include "ext/pb_ds/assoc_container.hpp"

#define PB push_back
#define PF push_front
#define LB lower_bound
#define UB upper_bound
#define fr(x) freopen(x,"r",stdin)
#define fw(x) freopen(x,"w",stdout)
#define REP(x, l, u) for(ll x = l;x<u;x++)
#define RREP(x, l, u) for(ll x = l;x>=u;x--)
#define complete_unique(a) a.erase(unique(begin(a),end(a)),end(a))
#define mst(x, a) memset(x,a,sizeof(x))
#define all(a) begin(a),end(a)
#define rall(a) rbegin(a),rend(a)
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define MP make_pair
#define lowbit(x) ((x)&(-(x)))
#define bitcnt(x) (__builtin_popcountll(x))
#define lson (ind<<1)
#define rson (ind<<1|1)
#define se second
#define fi first
#define sz(x) ((int)x.size())
#define EX0 exit(0);

typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ld;
using namespace __gnu_pbds; //required
using namespace std;
template<typename T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
typedef vector<ll> VLL;
typedef vector<int> VI;
const ll mod = 1e9 + 7;


string to_string (string s) { return '"' + s + '"'; }

string to_string (const char *s) { return to_string ((string) s); }

string to_string (bool b) { return (b ? "true" : "false"); }

template<typename A, typename B>
string to_string (pair<A, B> p) { return "(" + to_string (p.first) + ", " + to_string (p.second) + ")"; }

template<typename A>
string to_string (A v) {
    bool first = true;
    string res = "{";
    for (const auto &x : v) {
        if (!first) { res += ", "; }
        first = false;
        res += to_string (x);
    }
    res += "}";
    return res;
}

void debug_out () { cerr<<endl; }

template<typename Head, typename... Tail>
void debug_out (Head H, Tail... T) {
    cerr<<" "<<to_string (H);
    debug_out (T...);
}

#ifdef LOCAL
#define dbg(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
#define dbg(...) {}
#endif

template<typename T, typename S>
inline bool upmin (T &a, const S &b) { return a > b ? a = b, 1 : 0; }

template<typename T, typename S>
inline bool upmax (T &a, const S &b) { return a < b ? a = b, 1 : 0; }


ull twop (ll x) { return 1ULL<<x; }

ll MOD (ll a, ll m) {
    a %= m;
    if (a < 0)a += m;
    return a;
}

ll inverse (ll a, ll m) {
    a = MOD (a, m);
    if (a <= 1)return a;
    return MOD ((1 - inverse (m, a) * m) / a, m);
}

template<typename T>
T sqr (T x) { return x * x; }

ll gcd (ll a, ll b) {
    a = abs (a), b = abs (b);
    while (b != 0) {
        a %= b;
        swap (a, b);
    }
    return a;
}

ll fast (ll a, ll b, ll mod) {
    if (b < 0)a = inverse (a, mod), b = -b;
    ll ans = 1;
    while (b) {
        if (b & 1)ans = ans * a % mod;
        a = a * a % mod;
        b /= 2;
    }
    return ans % mod;
}

struct Primality {
    using int64 = long long;
    using pii = std::pair<int64, int>;
    
    template<typename T>
    T gcd (T a, T b) {
        return !b ? a : gcd (b, a % b);
    }
    
    inline int64 mul_mod (int64 a, int64 b, int64 mod) {
        if (mod < int (1e9)) return a * b % mod;
        int64 k = (int64) ((long double) a * b / mod);
        int64 res = a * b - k * mod;
        res %= mod;
        if (res < 0) res += mod;
        return res;
    }
    
    int64 pow_mod (int64 a, int64 n, int64 m) {
        int64 res = 1;
        for (a %= m; n; n >>= 1) {
            if (n & 1) res = mul_mod (res, a, m);
            a = mul_mod (a, a, m);
        }
        return res;
    }

public:
    // 用miller rabin素数测试判断n是否为质数
    bool is_prime (int64 n) {
        if (n <= 1) return false;
        if (n <= 3) return true;
        if (~n & 1) return false;
        const int u[] = {2, 3, 5, 7, 325, 9375, 28178, 450775, 9780504, 1795265022, 0};
        int64 e = n - 1, a, c = 0; // 原理：http://miller-rabin.appspot.com/
        while (~e & 1) e >>= 1, ++c;
        for (int i = 0; u[i]; ++i) {
            if (n <= u[i]) return true;
            a = pow_mod (u[i], e, n);
            if (a == 1) continue;
            for (int j = 1; a != n - 1; ++j) {
                if (j == c) return false;
                a = mul_mod (a, a, n);
            }
        }
        return true;
    }
    
    // 求一个小于n的因数，期望复杂度为O(n^0.25)，当n为非合数时返回n本身
    int64 pollard_rho (int64 n) {
        if (n <= 3 || is_prime (n)) return n; // 保证n为合数时可去掉这行
        while (1) {
            int i = 1, cnt = 2;
            int64 x = rand () % n, y = x, c = rand () % n;
            if (!c || c == n - 2) ++c;
            do {
                int64 u = gcd (n - x + y, n);
                if (u > 1 && u < n) return u;
                if (++i == cnt) y = x, cnt <<= 1;
                x = (c + mul_mod (x, x, n)) % n;
            } while (x != y);
        }
        return n;
    }
    
    // 使用rho方法对n做质因数分解，建议先筛去小质因数后再用此函数
    std::vector<pii> factorize (int64 n) {
        static const int sp[25] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79,
                                   83, 89, 97};
        std::vector<pii> fac;
        for (int i = 0; i < 25 && n > 1; ++i) {
            if (n % sp[i]) continue;
            int c = 0;
            while (n % sp[i] == 0) n /= sp[i], ++c;
            fac.emplace_back (sp[i], c);
        }
        std::vector<int64> u;
        if (n > 1) u.push_back (n);
        for (size_t i = 0; i < u.size (); ++i) {
            int64 x = pollard_rho (u[i]);
            if (x == u[i]) continue;
            u[i--] /= x;
            u.push_back (x);
        }
        std::sort (u.begin (), u.end ());
        for (size_t i = 0, j, m = u.size (); i < m; i = j) {
            for (j = i; j < m && u[i] == u[j]; ++j);
            fac.emplace_back (u[i], j - i);
        }
        return fac;
    }
    
    std::vector<int64> divisors (int64 n) {
        if (n == 1) return {1};
        auto fac = factorize (n);
        int m = fac.size ();
        std::vector<int64> ds;
        std::function<void (int, int64)> dfs = [&] (int d, int64 now) {
            if (d == m) {
                ds.emplace_back (now);
                return;
            }
            for (int i = 0, u = fac[d].second; i <= u; ++i) {
                dfs (d + 1, now);
                now *= fac[d].first;
            }
        };
        dfs (0, 1);
        std::sort (ds.begin (), ds.end ());
        return ds;
    }
} pf;

void EratosthenesSieve (const int n, vector<ll> &primes) {
    vector<ll> numbers (n + 1);
    for (ll i = 2; i <= n; i++) {
        if (!numbers[i]) {
            primes.PB (i);
            for (ll j = i * i; j <= n; j += i)numbers[j] = 1;
        }
    }
}

namespace SOLVE {
    map<ll, ll> cnt;
    map<ll, ll> rt;
    
    void main () {
        VLL primes;
        EratosthenesSieve (10010, primes);
        ll n;
        cin>>n;
        REP(i, 1, 100100)rt[i * i] = i;
        REP(i, 0, n) {
            ll a;
            cin>>a;
            for (auto p:primes) {
                if (p * p * p > a)break;
                if (a % (p * p * p) == 0) {
                    while (a % (p * p * p) == 0) {
                        a /= p * p * p;
                    }
                }
            }
            cnt[a]++;
        }
        ll ans = 0;
        for (auto i:cnt) {
            ll v = i.fi, c = i.se;
            if (!c)continue;
            dbg(v, c);
            if (v == 1)ans++;
            else {
                ll counter = 1;
                for (auto p:primes) {
                    if (p * p * p > v)break;
                    if (v % p == 0) {
                        if (v % (p * p) == 0) {
                            counter *= p;
                        } else {
                            counter *= p * p;
                        }
                        while (v % p == 0)v /= p;
                    }
                    if (counter >= 1e12) {
                        ans += i.se;
                        goto end;
                    };
                }
                dbg(v, counter);
                if (v == 1) {
                    ans += max (cnt[counter], c);
                    cnt[counter] = 0;
                } else if (rt.count (v)) {
                    counter *= rt[v];
                    ans += max (cnt[counter], c);
                    cnt[counter] = 0;
                } else if (pf.is_prime (v)) {
                    if (1.0 * counter * v * v > 1e11) {
                        ans += c;
                        continue;
                    }
                    counter *= v * v;
                    ans += max (cnt[counter], c);
                    cnt[counter] = 0;
                } else {
                    ans += c;
                }
            }
end:;
        }
        cout<<ans;
    }
}


signed main () {
#ifdef LOCAL
    fr("/Users/zhangqingchuan/Desktop/cp/cp/input.txt");
    fw("/Users/zhangqingchuan/Desktop/cp/cp/output.txt");
#endif
    
    
    int t = 1;
//    cin >> t;
    for (int i = 1; i <= t; i++) {
//        cout<<"Case #"<<i<<": ";
        SOLVE::main ();
        
    }








//    clock_t st = clock();
//    while(clock() - st < 3.0 * CLOCKS_PER_SEC){
//
//    }
    
    
    
    
    
    
    return 0;
}