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

using namespace std;

const int N = 100010;

typedef long long LL;

int n, pri_cnt = 0;

LL a[N], p1[N], p2[N], pri[N];

void pre_pri() {

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

        if (pri[i]) continue;

        pri[++pri_cnt] = i;

        for (int j = i + i; j < N; j += i) pri[i] = 1;

    }

}

void cal(LL x, int id) {

    p1[id] = p2[id] = 1;

    for (int i = 1; pri[i] * pri[i] * pri[i] <= x; i++) {

        int t = 0;

        while (x % pri[i] == 0) x /= pri[i], t++;

        t %= 3;

        for (int j = 0; j < t; j++) p1[id] *= pri[i];

        t = (3 - t) % 3;

        for (int j = 0; j < t; j++) p2[id] *= pri[i];

    }

    if (x) {

        LL t = sqrt(x);

        if (t * t == x)

            p1[id] *= x, p2[id] *= t;

        else

            p1[id] *= x, p2[id] *= x * x;

    }

}

map<LL, int> mp;

int main() {

    pre_pri();

    scanf("%d", &n);

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

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

        cal(a[i], i);

    }

    int ans = 0;

    for (int i = 1; i <= n; i++) mp[p1[i]]++;

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

    	if (mp[p1[i]] == 0) continue;

        if (p1[i] == p2[i]) {

            ans++;

            mp[p1[i]] = 0;

            continue;

        }

        ans += max(mp[p1[i]], mp[p2[i]]);

        mp[p1[i]] = mp[p2[i]] = 0;

    }

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

    return 0;

}

// Faster C++ solution for the same problem (measured speedup: 2.5620224804670655x):
#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;

}