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: Time Limit Exceeded)

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <unordered_map>
#include <utility>
#define FR first
#define SE second

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<ull,ull> pr;

inline ll mul(ll x,ll y,ll MOD) {
  x%=MOD;y%=MOD;
  ll ans=0;
  while (y) {
    if (y&1) ans=(ans+x)%MOD;
    x=(x+x)%MOD;
    y>>=1;
  }
  return ans;
}
 
ll gcd(ll x,ll y) {
  return (x%y==0)?y:gcd(y,x%y);
}
 
ll pow_mod(ll x,ll k,ll MOD) {
  ll ans=1;
  while (k) {
    if (k&1) ans=mul(ans,x,MOD);
    x=mul(x,x,MOD);
    k>>=1;
  }
  return ans;
}
 
bool is_prime(int c,ll n) {
  ll d=n-1;
  while (!(d&1)) d>>=1;
  ll t=pow_mod(c,d,n);
  while (d!=n-1&&t!=n-1&&t!=1) {
    t=mul(t,t,n);
    d<<=1;
  }
  return (t==n-1)||(d&1);
}
 
const int pri[15]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47};
 
bool miller_rabin(ll n) {
  if (n==1) return 0;
  for(int i=0;i<15;i++) {
    if (n==pri[i]) return 1;
    if (n%pri[i]==0) return 0;
  }
  for(int i=1;i<=3;i++) {
    int c=rand()%(n-2)+2;
    if (!is_prime(c,n)) return 0; 
  }
  return 1;
}

int prime[3005],tot;
bool check[3005];

void pre() {
  int N=pow(1e10,1.0/3);
  for(int i=2;i<=N;i++) {
  	if (!check[i]) prime[++tot]=i;
  	for(int j=1;j<=tot&&i*prime[j]<=N;j++) {
  		check[i*prime[j]]=1;
  		if (i%prime[j]==0) break;
	  }
  }
}

unordered_map <ll,ull> mp;

ull rd() {
  return (ull)rand()*rand()*1063094364578754ull+rand();
}

ull getrd(ll x) {
  if (!mp.count(x)) mp[x]=rd();
  return mp[x];
}

pr now[15];

pr calc(int n) {
  ull s1=0,s2=0;
  for(int i=1;i<=n;i++)
    if (now[i].SE%3) {
    	now[i].SE%=3;
    	s1^=getrd(now[i].FR*now[i].SE);
    	s2^=getrd(now[i].FR*(3-now[i].SE));
	}
  return pr(s1,s2);
}

pr a[100005];
ull num[100005];
int sum[100005];
bool vis[100005];

int main() {
  srand(19260817);
  pre();
  int n;
  scanf("%d",&n);
  int m=0,s1=0,s2=0;
  for(int i=1;i<=n;i++) {
  	ll x;
  	scanf("%lld",&x);
  	int cnt=0;
  	for(int j=1;j<=tot&&prime[j]<=x;j++)
  	  if (x%prime[j]==0) {
  	  	  now[++cnt]=pr(prime[j],0);
  	  	  while (x%prime[j]==0) {
  	  	  	    now[cnt].SE++;
  	  	  	    x/=prime[j];
			  }
		}
	if (x>1) {
		ll t=sqrt(x);
		while (t*t>x) t--;
		while (t*t<x) t++;
		if (t*t==x) now[++cnt]=pr(t,2);
		else if (miller_rabin(x)) now[++cnt]=pr(x,1);
		else {
			s1++;
			continue;
		}
	}
	pr t=calc(cnt);
	if (t.FR) {
		a[++m]=t;
		num[m]=t.FR;
	}
	else s2=1;
  }
  sort(num+1,num+m+1);
  for(int i=1;i<=m;i++) {
  	a[i].FR=lower_bound(num+1,num+m+1,a[i].FR)-num;
  	sum[a[i].FR]++;
  	ull t=a[i].SE;
  	a[i].SE=lower_bound(num+1,num+m+1,a[i].SE)-num;
  	if (num[a[i].SE]!=t) a[i].SE=0;
  }
  int ans=0;
  for(int i=1;i<=m;i++)
    if (!vis[a[i].FR]) {
    	ans+=max(sum[a[i].FR],sum[a[i].SE]);
    	vis[a[i].FR]=vis[a[i].SE]=1;
	}
  printf("%d\n",ans+s1+s2);
  return 0;
}