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: Accepted)

#include <iostream>
#include <map>
#include <algorithm>

#define rep(i, n) for(int i = 0; i < (n); ++i)

using namespace std;

typedef long long ll;

int n;
ll s[100000];
ll nrml[100000];
bool p[100000];
vector<int> pt;
vector<int> pm;
vector<ll> ps;
map<ll, int> cnrm;

void prm(){
	fill_n(p + 2, 100000 - 2, true);
	rep(i, 100000){
		if(p[i]){
			for(int j = 2 * i; j < 100000; j += i){
				p[j] = false;
			}

			if(i < 3000){
				pt.push_back(i);
			}
			pm.push_back(i);
			ps.push_back(ll(i) * i);
		}
	}
}

ll nrm(ll x){
	for(int v: pt){
		ll v3 = ll(v) * v * v;
		while(x % v3 == 0){
			x /= v3;
		}
	}
	return x;
}

ll pr(ll x){
	ll k = 1;
	for(int v: pt){
		if(x % (v * v) == 0){
			x /= (v * v);
			k *= v;
		}
		else if(x % v == 0){
			x /= v;
			k *= v * v;	
		}
	}
	if(binary_search(ps.begin(), ps.end(), x)){
		int idx = lower_bound(ps.begin(), ps.end(), x) - ps.begin();
		return pm[idx] * k;
	}
	return x * x * k;
}

int main(){
	cin >> n;
	rep(i, n){
		cin >> s[i];
	}

	prm();

	rep(i, n){
		nrml[i] = nrm(s[i]);
		++cnrm[nrml[i]];		
	}

	int ans = 0;
	rep(i, n){
		ll a = nrml[i];
		ll b = pr(a);

		if(a == 1 && cnrm[a]){
			++ans;
			cnrm[a] = 0;
		}
		else{
			ans += max(cnrm[a], cnrm[b]);
			cnrm[a] = cnrm[b] = 0;
		}
	}
	cout << ans << endl;
	return 0;
}