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)

#include <iostream>
#include <cassert>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <set>
#include <map>
#include <iomanip>
#include <math.h>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <fstream>

#define REP(i, n) for (int i = 0; i < n; ++i)
#define FOR(i, a, b) for (int i = a; i < b; ++i)
#define DB(x) cerr << #x << ": " << x << endl;
#define pb push_back
#define mp make_pair
#define fi first
#define se second

using namespace std;

typedef long long LL;
typedef long double LD;

typedef pair<int, int> pii;

const int MAXN = 100000;
const int MOD = 1000 * 1000 * 1000 + 7;

void solve();

int main()
{
    auto start = clock();
    cout.sync_with_stdio(0);
    cin.tie(0);
    cout.precision(10);
    cout << fixed;

#ifdef HOME
    //freopen("input.txt", "r", stdin);
    freopen("biginput.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
#endif

    int t = 1;
    //cin >> t;
    while (t--) {
        solve();
    }

    cerr << "\nTime: " << (clock() - start) / 1.0 / CLOCKS_PER_SEC << "\n";

    return 0;
}

vector<int> genPrimes(int upperBound)
{
    vector<int> primes;
    vector<char> sieved(upperBound, false);
    for (int i = 2; i < upperBound; ++i) {
        if (!sieved[i]) {
            primes.pb(i);
            for (int j = 2 * i; j < upperBound; j += i) {
                sieved[j] = true;
            }
        }
    }
    return primes;
}

const int MAXP = 100000;

LL myPow(LL base, int val)
{
    if (val == 0) {
        return 1;
    }
    if (val == 1) {
        return base;
    }
    if (val == 2) {
        return base * base;
    }
    return -1;
}

LL MAXPATTERN = 100000LL * 100000LL;

void gen(int size)
{
    ofstream ofs("biginput.txt");
    ofs << size << endl;
    REP(i, size)
    {
        ofs << MAXPATTERN - size + i + 1 << endl;
    }
}

void solve()
{
    //gen(100000);
    //return;
    int n;
    cin >> n;
    vector<LL> s(n);
    REP(i, n) {
        cin >> s[i];
    }
    auto primes = genPrimes(MAXP + 10);
    unordered_map<LL, int> counts;
    unordered_map<LL, LL> antiMap;
    int ans = 0;
    REP(i, n) {
        LL pattern = 1;
        LL antiPattern = 1;
        for (int p : primes) {
            int cnt = 0;
            while (s[i] % p == 0) {
                ++cnt;
                s[i] /= p;
            }
            cnt %= 3;
            pattern *= myPow(p, cnt);
            antiPattern *= myPow(p, (3 - cnt) % 3);
            assert(pattern > 0);
            assert(antiPattern > 0);
            if (antiPattern > MAXPATTERN) {
                break;
            }

            if (s[i] == 1) {
                break;
            }
            if (p > 2200) {
               LL x = sqrtl(s[i]) - 10;
                while (x * x < s[i]) {
                    ++x;
                }
                if (x * x == s[i]) {
                    pattern *= myPow(x, 2);
                    antiPattern *= myPow(x, 1);
                    s[i] /= x * x;
                }
                break;
            }
        }
        if (s[i] != 1) {
            ++ans;
        } else {
            assert(pattern > 0);
            assert(antiPattern > 0);
            ++counts[pattern];
            antiMap[pattern] = antiPattern;
            antiMap[antiPattern] = pattern;
        }
    }
    for (const auto& p : antiMap) {
        auto pattern = p.first;
        auto antiPattern = p.second;
        if (pattern < antiPattern) {
            continue;
        }

        if (pattern == antiPattern) {
            ans += min(counts[pattern], 1);
        } else {
            ans += max(counts[pattern], counts[antiPattern]);
        }
    }
    cout << ans << endl;
}