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

#ifndef LOCAL

#pragma GCC optimize(3)

#define lld "%lld"

#else

#define lld "%I64d"

#endif

using namespace std;

typedef long long ll;

const int inf=0x3f3f3f3f;

const int maxn=1e5;

ll p[maxn];

bool vis[maxn];

map<ll, int>cnt;

int pCnt;

void init() {

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

        if (!vis[i]) p[pCnt++]=i;

        for (int j=0; j<pCnt && p[j]*i<maxn; j++) {

            vis[i*p[j]]=1;

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

        }

    }

}

ll da1[maxn], da2[maxn];

void deal(int id) {

    ll ans1=1, ans2=1;

    ll tmp=da1[id];

    for (int i=0; p[i]*p[i]*p[i]<=tmp; i++) {

        int tot=0;

        while (tmp%p[i]==0) {

            tot++;

            tmp /= p[i];

        }

        tot%=3;

        if (tot==1) {

            ans1*=p[i];

            ans2*=p[i]*p[i];

        } else if (tot==2) {

            ans1*=p[i]*p[i];

            ans2*=p[i];

        }

    }

    ll sqrTmp=sqrt(tmp);

    if (sqrTmp*sqrTmp==tmp) {

        ans1*=tmp;

        ans2*=sqrTmp;

    } else {

        ans1*=tmp;

        ans2*=tmp*tmp;

    }

    da1[id]=ans1; da2[id]=ans2;

    cnt[ans1]++;

}

int main() {

#ifdef LOCAL

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

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

#endif

    int n; 

    init();

    scanf("%d", &n);

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

        scanf(lld, da1+i);

        deal(i);

    }

    int ans=0;

    if (cnt[1]) ans++, cnt[1]=0;

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

        ans += max(cnt[da1[i]], cnt[da2[i]]);

        cnt[da1[i]]=cnt[da2[i]]=0;

    }

    printf("%d", ans);

    return 0;

}

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

}