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++ (GCC 9.2.1) (judge verdict: Accepted)

#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
using namespace std;
 
#define int __int128
#define long __int128
 
ostream &operator<<(ostream &os, __int128_t value) {
    if (ostream::sentry(os)) {
        __uint128_t tmp = value < 0 ? -value : value;
        char buffer[64];
        char *d = end(buffer);
        do {
            --d;
            *d = "0123456789"[tmp % 10];
            tmp /= 10;
        } while (tmp != 0);
        if (value < 0) {
            --d;
            *d = '-';
        }
        int len = end(buffer) - d;
        if (os.rdbuf()->sputn(d, len) != len) {
            os.setstate(ios_base::badbit);
        }
    }
    return os;
}
 
istream &operator>>(istream &is, __int128_t &value) {
    string in;
    is >> in;
    value = 0;
    for (const char &c : in) {
        if ('0' <= c && c <= '9') value = 10 * value + (c - '0');
    }
    if (in[0] == '-') value *= -1;
    return is;
}

signed main(){
    int N;
    cin >> N;
    vector<bool> sieve_of_primes(1e5, true);
    for(int i = 2; i * i < 1e5; i++){
        if(sieve_of_primes[i]){
            for(int j = i * 2; j < 1e5; j += i){
                sieve_of_primes[j] = false;
            }
        }
    }
    vector<long> primes;
    for(int i = 2; i < 1e5; i++){
        if(sieve_of_primes[i]){
            primes.push_back(i);
        }
    }
    map<long, int> nums;
    bool is_in_1 = false;
    for(int i = 0; i < N; i++){
        long num;
        cin >> num;
        for(long j = 0; primes[j] * primes[j] * primes[j] <= num; ){
            if(num % (primes[j] * primes[j] * primes[j]) == 0){
                num /= primes[j] * primes[j] * primes[j];
            }else{
                j++;
            }
        }
        if(num == 1){
            is_in_1 = true;
        }else{
            nums[num]++;
        }
    }
    long ans = 0;
    for(auto item: nums){
        pair<long, int> i = item;
        long i_tmp = i.first;
        long cube_pair_another = 1;
        for(long j = 0; primes[j] * primes[j] * primes[j] <= i.first; j++){
            if(i.first % (primes[j] * primes[j]) == 0){
                cube_pair_another *= primes[j];
                i_tmp /= primes[j] * primes[j];
            }else if(i.first % primes[j] == 0){
                cube_pair_another *= primes[j] * primes[j];
                i_tmp /= primes[j];
            }
        }
        cube_pair_another *= i_tmp * i_tmp;
        ans += max(i.second, nums[cube_pair_another]);
        nums[i.first] = 0;
        if(nums[cube_pair_another]){
            nums[cube_pair_another] = 0;
        }else{
            nums.erase(cube_pair_another);
        }
    }
    cout << ans + is_in_1 << endl;
}