// Slower C++ solution:
#include<cstdio>

#include<cstring>

#include<algorithm>

#include<vector>

#include<map>

#include<cmath>

#define MAXN 100000

#define MAXV 20000

using namespace std;

typedef long long LL;

vector<int> prime;

LL seq[MAXN+5],a[MAXN+5],b[MAXN+5];

bool vis[MAXV+5];

map<LL,int> mp;

void prepare()

{

	for(int i=2;i<=MAXV;i++)

	{

		if(vis[i]==false)

			prime.push_back(i);

		for(int j=0;1LL*prime[j]*i<=MAXV;j++)

		{

			vis[i*prime[j]]=true;

			if(i%prime[j]==0)

				break;

		}

	}

}

void Work(int i,LL x)

{

	a[i]=b[i]=1;

	for(int j=0;1LL*prime[j]*prime[j]*prime[j]<=x;j++)

	{

		LL t1=prime[j],t2=1LL*prime[j]*prime[j],t3=1LL*prime[j]*prime[j]*prime[j];

		while(x%t3==0)	x/=t3;

		if(x%t2==0)			a[i]*=t2,b[i]*=t1;

		else if(x%t1==0)	a[i]*=t1,b[i]*=t2;

		while(x%t1==0)	x/=t1;

	}

	if(x!=1LL)

	{

		LL t=(LL)sqrt(x);

		if(t*t==x)	a[i]*=x,b[i]*=t;

		else		a[i]*=x,b[i]*=x*x;

	}

}

int main()

{

//	freopen("anticube.in","r",stdin);

//	freopen("anticube.out","w",stdout);

	prepare();

	int N;

	scanf("%d",&N);

	for(int i=1;i<=N;i++)

	{

		scanf("%lld",&seq[i]);

		Work(i,seq[i]);

		mp[a[i]]++;

	}

	int ans=0;

	for(int i=1;i<=N;i++)

		if(mp.find(a[i])!=mp.end())

		{

			if(a[i]==b[i])

			{

				ans++;

				mp.erase(mp.find(a[i]));

			}

			else

			{

				int ansn=mp[a[i]];

				mp.erase(mp.find(a[i]));

				if(mp.find(b[i])!=mp.end())

				{

					ansn=max(ansn,mp[b[i]]);

					mp.erase(mp.find(b[i]));

				}

				ans+=ansn;

			}

		}

	printf("%d\n",ans);

	return 0;

}

// Faster C++ solution for the same problem (measured speedup: 1.2269752419419222x):
#include<map>

#include<cstdio>

#include<algorithm>

using namespace std;

typedef long long ll;

const int MAX = 2160;

const int MAXN = 100000;

int prm[MAX + 5], pcnt = 0;

bool is_prm[MAX + 5];

void init() {

	for(int i=2;i<=MAX;i++) {

		if( !is_prm[i] )

			prm[++pcnt] = i;

		for(int j=1;i*prm[j]<=MAX;j++) {

			is_prm[i*prm[j]] = true;

			if( i % prm[j] == 0 ) break;

		}

	}

}

ll s[MAXN + 5], a[MAXN + 5], b[MAXN + 5];

ll IsSqr(ll x) {

	ll le = 1, ri = 100000;

	while( le < ri ) {

		ll mid = (le + ri) >> 1;

		if( mid * mid >= x ) ri = mid;

		else le = mid + 1;

	}

	return (ri * ri == x) ? ri : 0;

}

map<ll, int>mp;

int siz[2*MAXN + 5];

int main() {

	init(); int N;

	scanf("%d", &N);

	int ans = 0, flag = false;

	for(int i=1;i<=N;i++) {

		a[i] = b[i] = 1;

		scanf("%lld", &s[i]);

		for(int j=1;j<=pcnt;j++) {

			int cnt = 0;

			while( s[i] % prm[j] == 0 ) {

				cnt++;

				s[i] /= prm[j];

			}

			cnt %= 3;

			if( cnt == 1 ) {

				a[i] *= prm[j];

				b[i] *= prm[j] * prm[j];

			}

			else if( cnt == 2 ) {

				a[i] *= prm[j] * prm[j];

				b[i] *= prm[j];

			}

		}

		if( IsSqr(s[i]) ) {

			a[i] *= s[i];

			b[i] *= IsSqr(s[i]);

		}

		else {

			a[i] *= s[i];

			b[i] *= s[i] * s[i];

		}

		if( !flag && a[i] == 1 && b[i] == 1 )

			flag = true;

	}

	for(int i=1;i<=N;i++) {

		if( a[i] == 1 && b[i] == 1 ) continue;

		if( mp.count(a[i]) )

			siz[mp[a[i]]]++;

		else {

			mp[a[i]] = i;

			mp[b[i]] = i+N;

			siz[i]++;

		}

	}

	for(int i=1;i<=N;i++) {

		if( mp[a[i]] == i )

			ans += max(siz[i], siz[i+N]);

	}

	if( flag ) ans++;

	printf("%d\n", ans);

}