// Original C++ solution (slower):
#include <bits/stdc++.h>



#define f first 

#define s second 

#define pb push_back               

#define mp make_pair 



using namespace std;                    



typedef long long ll;

typedef pair<int, int> pii;

typedef pair<long long, long long> pll;



const int M = (int)4e3, N = (int)1e5 + 123, mod = (int)1e9 + 7;

bool was[M];

vector< ll > p;

map< ll, ll> sr, sq, cnt, anti;

ll n, a[N], ans;

bool ok;

          

void add1(ll x){

	for(auto j : p){

		int cnt= 0;

		while(x % j == 0)

			x /= j, cnt++;

    }



    if(x != 1){

    	ll sx = sqrt(x);

    	while(sx * sx < x)

    		sx++;

    	while(sx * sx > x)

    		sx--;

    	if(sx * sx == x){

    		sr[x] = sx;

    		sq[sx] = x;

    	}

    } 

}



void add(ll x){

	ll y = 1, z = 1;

	for(auto j : p){

		int cnt= 0;

		while(x % j == 0)

			x /= j, cnt++;

 		

 		if(cnt % 3 == 2)

   			y *= j * j, z *= j;

	   	

	   	if(cnt % 3 == 1)

   			y *= j, z *= j * j;

    }



    if(x != 1){

    	if(sr.count(x) || sq.count(x)){

    		if(sr.count(x)){

    			y *= x;

    			z *= sr[x];

    		}else{

    			y *= x;

    			z *= sq[x];

    		}

    	}else{

    		ans++;

    		return;

    	}

    } 

    if(y == 1){

    	if(ok)

    		return;

    	ok = 1;

    	ans++;

    	return;

    }

    cnt[y]+=1;

    cnt[z]+=0;

    anti[y] = z;

    anti[z] = y;

}



int main(){    

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

		if(!was[i]){

			p.pb(i);

			for(int j = i; j < M; j += i)

				was[j] = 1;

		}

	}

	/*

	ll x = p.back();

	cout << p.size() << endl;

	cout << x << endl;

	cout << x * x * x / 1e10 << endl;

	*/

	cin >> n;

	for(int i = 0; i < n; i++){

		cin >> a[i];

		add1(a[i]);

	}



	for(int i = 0; i < n; i++)

		add(a[i]);



	for(auto it : cnt){

		//cerr << it.f << " " << it.s << endl;

		ll x = it.f;

		ll y = anti[x];

		if(x < y)

			ans += max(cnt[x], cnt[y]);

	} 

	cout << ans;

	return 0;

}


// Optimized solution to the same problem (faster):
#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);

}

// Fastest known solution for this problem: