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



using namespace std;



int n;

long long a[100005];

bool ex = false;

multiset<long long> s, ss;

map<long long, int> f;



int spf[100005];



const int MAXN = 100001;



void sieve() {

    spf[1] = 1;

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

        spf[i] = i;

 	for (int i=4; i<MAXN; i+=2)

        spf[i] = 2;

    for (int i=3; i*i<MAXN; i++)

    {

        if (spf[i] == i)

        {

            for (int j=i*i; j<MAXN; j+=i)

                if (spf[j]==j)

                    spf[j] = i;

        }

    }

}





long long get(long long x) {

	long long ou = 1;

	set<int> vis;

	while (x != 1) {

		if (vis.find(spf[x]) == vis.end()) {

			ou *= spf[x];

			vis.insert(spf[x]);

		}

		x /= spf[x];

	}

	return ou;

}



long long p(long long n) {

	return n*n*n;  

}



signed main() {

	sieve();

	scanf("%d", &n);

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

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

		s.insert(a[i]);

	}

	for (int i = 1; 1ll*i*i*i <= 10000000000; i ++) {

		if (s.find(1ll*i*i*i) != s.end()) {

			ex = true;

			s.erase(1ll*i*i*i);

			ss.insert(1ll*i*i*i);

		}

	}

	//cout << s.size() << endl;

	int res = 0;

	if (ex) res++;

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

		if (ss.find(a[i]) != ss.end()) continue;

		for (int j = 2154; j >= 1; j--) {

			if (a[i] % (1ll*j*j*j) == 0) {

				a[i] /= 1ll*j*j*j;

			}

		}

		f[a[i]]++;

	}

	sort(a+1, a+1+n);

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

		if (ss.find(a[i]) != ss.end()) continue;

		//cout << a[i] << endl;

		if (a[i] > 100000) {res += f[a[i]]; f[a[i]] = 0;}

		else {

			long long op = p(get(a[i]))/a[i];

			res += max(f[a[i]], f[op]);

			f[op] = 0;

			f[a[i]] = 0;

		}

	}	

	cout << res;

}

// Faster C++ solution for the same problem (measured speedup: 1.3270674326771943x):
#include <bits/stdc++.h>

#include <ext/pb_ds/assoc_container.hpp>

#include <ext/pb_ds/trie_policy.hpp>

#include <ext/rope>



#pragma 03



using namespace std;

using namespace __gnu_pbds;

using namespace __gnu_cxx;



mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());



#define fi first

#define se second

#define pb push_back

#define eb emplace_back

#define mp make_pair

#define gcd __gcd

#define fastio ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)

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

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

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

#define rall(x) (x).rbegin(), (x).rend()

#define endl "\n"



typedef long long ll;

typedef unsigned long long ull;

typedef unsigned uint;

typedef long double ld;

typedef pair<int, int> pii;

typedef pair<ll, ll> pll;

typedef vector<int> vi;

typedef vector<vector<int>> vvi;

typedef vector<ll> vll;

typedef vector<vector<ll>> vvll;

typedef vector<bool> vb;

typedef vector<vector<bool>> vvb;

template<typename _def> using ordered_set=tree<_def, null_type, less<_def>, rb_tree_tag, tree_order_statistics_node_update>;

typedef trie<string, null_type, trie_string_access_traits<>, pat_trie_tag, trie_prefix_search_node_update> pref_trie;



struct custom_hashes {

    inline static uint64_t splitmix64(uint64_t x) {

        // http://xorshift.di.unimi.it/splitmix64.c

        x += 0x9e3779b97f4a7c15;

        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;

        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;

        return x ^ (x >> 31);

    }



    template<typename T> //should take care of all types that can turn into integers

    size_t operator()(T x) const {

        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();

        return splitmix64((uint64_t)x + FIXED_RANDOM);

    }

};



template<typename _F, typename _T> using safe_map=gp_hash_table<_F, _T, custom_hashes>;



constexpr int N=1e5+1;

bitset<N+1> isprime;

void init() {

    isprime.set();

    for(int i=2; i*i<=N; i++) if(isprime[i]) for(int j=i*i; j<=N; j+=i) isprime[j]=0;

}



int32_t main() {

    //freopen("gen.txt", "r",  stdin);

    fastio;

    safe_map<ll, int> cnt;

    safe_map<ll, ll> rev;

    init();

    int n; cin>>n;

    rep(i, n) {

        ll x; cin>>x;

        if(x==1) cnt[1]++, rev[1]=1;

        else {

            ll val=1, rval=1;

            for(int i=2; 1LL*i*i*i<=x; i++) {

                if(x%i==0) {

                    int cnt=0;

                    while(x%i==0) x/=i, cnt++;

                    cnt%=3;

                    rep(j, cnt) val*=i;

                    rep(j, (3-cnt)%3) if(rval!=-1) {

                        rval*=i;

                        if(rval>1e11) rval=-1;

                    }

                }

            }

            if(x>1) {

                if(sqrt(x)==trunc(sqrt(x))&&isprime[trunc(sqrt(x))]) rval*=trunc(sqrt(x));

                else {

                    if(rval>1e11/x/x) rval=-1;

                    else rval*=x*x;

                }

                val*=x;

            }

            cnt[val]++; rev[val]=rval;

        }

    }

    int ans1=0, ans2=0;

    for(auto& it: cnt) {

        //cout<<it.fi<<' '<<it.se<<' '<<rev[it.fi]<<endl;

        if(rev[it.fi]!=it.fi&&cnt.find(rev[it.fi])!=cnt.end()) ans1+=max(it.se, cnt[rev[it.fi]]);

        else if(rev[it.fi]==it.fi) ans2++;

        else ans2+=it.se;

    }

    cout<<ans1/2+ans2<<endl;

}