// Slower C++ solution:
//#include <bits/stdc++.h>

#include <ext/pb_ds/hash_policy.hpp>

#include <ext/pb_ds/assoc_container.hpp>

#include <iostream>

#include <algorithm>

#include <vector>

#include <queue>

#include <stack>

#include <set>

#include <map>

#include <cstring>

#include <cmath>



#define X first

#define Y second

#define ls rt<<1

#define rs rt<<1|1

#define getmid ((l+r)>>1)

#define PB push_back

#define EP emplace_back

#define MP make_pair

#define lowbit(x) ((x)&-(x))

#define ALL(x) x.begin(),x.end()

#define mst(x,a) memset(x, a, sizeof(x))

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

#define rep1(i,n) for(int i=1; i<=(n); i++)

#ifdef LOCAL

    #define dbg(a) cout << #a": " << a << endl;

#else

    #define dbg(a)

#endif // LOCAL



using namespace std;

using namespace __gnu_pbds;

typedef long long ll;

const int inf = 0x3f3f3f3f;

const ll INF = 0x3f3f3f3f3f3f3f3fll;

typedef pair<int,int> pii;

typedef pair<double,double> pdd;



const int N = 2200 + 10;

const int M = 1e5 + 10;

const int mod = 998244353;

const double eps = 1e-10;

const double pi = acos(-1.0);



int n;

ll a[M];

int prime[N+1],tot;

vector<ll> ve;

gp_hash_table<ll,int> cnt;

gp_hash_table<ll,ll> mp;



void getPrime(){

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

        if(!prime[i]) prime[++tot] = i;

        for(int j=1; j<=tot && prime[j]<=N/i; j++){

            prime[i*prime[j]] = 1;

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

        }

    }

}



inline bool check(ll n){

    ll m = sqrt(n+0.5);

    return n==m*m;

}



int main()

{

#ifdef LOCAL

    freopen("in.txt","r",stdin);

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

#endif // LOCAL

    ios::sync_with_stdio(false);

    cin.tie(0);

    cout.tie(0);



    getPrime();

    cin>>n;

    for(int i=1; i<=n; i++) cin>>a[i];

    int ans = 0;

    bool one = false;

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

        ll t = a[i];

        ll x = 1, y = 1;

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

            if(t%prime[j]==0){

                int num = 0;

                while(t%prime[j]==0) {

                    t /= prime[j];

                    num++;

                }

                num %= 3;

                for(int k=1; k<=num; k++) x *= prime[j];

                for(int k=(3-num)%3; k; k--) y *= prime[j];

            }

            if(t==1) break;

        }

        if(t!=1) {

            if(check(t)) {

                x *= t;

                y *= (int)sqrt(t+0.5);

            } else {

                if((double)t*t*y<=1e10) {

                    x *= t;

                    y *= t*t;

                } else {

                    ans++;

                    continue;

                }

            }

        }

        if(x==1) {

            if(!one) {

                one = true;

                ans++;

            }

            continue;

        }

        mp[x] = y;

        if(++cnt[x]==1) ve.PB(x);

    }

    for(ll val: ve) {

        if(!cnt[val]) continue;

        int x = cnt[val];

        int y = cnt[mp[val]];

        ans += max(x, y);

        cnt[mp[val]] = 0;

    }

    cout<<ans<<endl;



    return 0;

}


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

#include <cmath>

#include <cstdio>



typedef long long LL;



const int MAXN = 1e5 + 5;



template<typename _T>

void read( _T &x )

{

	x = 0;char s = getchar();int f = 1;

	while( s > '9' || s < '0' ){if( s == '-' ) f = -1; s = getchar();}

	while( s >= '0' && s <= '9' ){x = ( x << 3 ) + ( x << 1 ) + ( s - '0' ), s = getchar();}

	x *= f;

}



template<typename _T>

void write( _T x )

{

	if( x < 0 ){ putchar( '-' ); x = ( ~ x ) + 1; }

	if( 9 < x ){ write( x / 10 ); }

	putchar( x % 10 + '0' );

}



template<typename _T>

_T MAX( const _T a, const _T b )

{

	return a > b ? a : b;

}



std :: map<LL, int> mp;



LL a[MAXN], oppo[MAXN];

LL pw2[MAXN], pw3[MAXN];



int prime[MAXN], pn;

int N;



bool isPrime[MAXN];



void EulerSieve( const int siz )

{

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

	{

		if( ! isPrime[i] ) prime[++ pn] = i;

		for( int j = 1 ; j <= pn && 1ll * i * prime[j] <= siz ; j ++ )

		{

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

			if( ! ( i % prime[j] ) ) break;

		}

	}

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

		pw2[i] = 1ll * prime[i] * prime[i], pw3[i] = 1ll * pw2[i] * prime[i];

}



int main()

{

	bool flg = false;

	read( N ); EulerSieve( 3000 );

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

	{

		read( a[i] );

		for( int k = 1 ; k <= pn && pw3[k] <= a[i] ; k ++ )

			while( ! ( a[i] % pw3[k] ) )

				a[i] /= pw3[k];

		if( a[i] == 1 ) flg = true, mp[a[i]] = -1;

		else

		{

			mp[a[i]] ++;

			LL tmp = a[i];

			int tot = 0, indx; LL rest = 1;

			for( int k = 1 ; k <= pn && prime[k] <= tmp ; k ++ )

				if( ! ( tmp % prime[k] ))

				{

					tot ++, indx = 0;

					while( ! ( tmp % prime[k] ) )

						indx ++, tmp /= prime[k];

					if( indx & 1 ) rest = 1ll * rest * pw2[k];

					else rest = 1ll * rest * prime[k];

				}

			int t = sqrt( tmp );

			if( 1ll * t * t == tmp ) oppo[i] = 1ll * t * rest;

			else oppo[i] = ( tmp <= 1e5 ? rest * tmp * tmp : 0 );

		}

	}

	int ans = 0;

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

		if( ~ mp[a[i]] )

			ans += MAX( mp[a[i]], mp[oppo[i]] ),

			mp[a[i]] = mp[oppo[i]] = -1;

	write( ans + flg ), putchar( '\n' );

	return 0;

}