// Slower C++ solution:
#include <iostream>

#include <cstdio>

#include <cassert>

#include <cstring>

#include <vector>

#include <valarray>

#include <array>

#include <queue>

#include <set>

#include <unordered_set>

#include <map>

#include <unordered_map>

#include <algorithm>

#include <cmath>

#include <complex>

#include <random>



using namespace std;

using ll = long long;

using ull = unsigned long long;

template<class T = ll> constexpr T TEN(int n) {return (n==0)?1:10*TEN<T>(n-1);}



const int MP = 100100;

vector<int> pr;

vector<ull> bpr;



void first() {

    bool used[MP] = {};

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

        if (used[i]) continue;

        pr.push_back(i);

        ull x = ((__int128(1)<<64) + i-1 ) / i;

        bpr.push_back(x);

        for (int j = 2*i; j < MP; j += i) {

            used[j] = true;

        }

    }

}



map<ll, int> fact(ll n) {

    int pc = (int)pr.size();

    map<ll, int> mp;

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

        ll d = pr[i]; ull rd = bpr[i];

//        if (n < d*d) break;

        while (true) {

            ll nd = __int128(n)*rd >> 64;

            if (nd * d != n) break;

            n = nd;

            mp[d]++;

        }

    }

    if (n > 1) mp[n]++;

    return mp;

}



ll mul(ll a, ll b) {

    if (TEN(12)/a < b) return TEN(12);

    return a*b;

}



int main() {

    first();

    using P = pair<ll, ll>;

    map<P, P> g;

    int n;

    scanf("%d", &n);

    bool one = false;

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

        if (i % 1000 == 0) {

//            cout << i << " " << gc << endl;

        }

        ll s;

        scanf("%lld", &s);

        map<ll, int> fac = fact(s);

        ll d0 = 1, d1 = 1;

        for (auto p: fac) {

            p.second %= 3;

            if (p.second == 1) {

                d0 = mul(d0, p.first);

                d1 = mul(d1, p.first);

                d1 = mul(d1, p.first);

            } else if (p.second == 2) {

                d0 = mul(d0, p.first);

                d0 = mul(d0, p.first);

                d1 = mul(d1, p.first);

            }

        }

        if (d0 == 1) {

            one = true;

            continue;

        }

        if (d0 < d1) {

            g[P(d0, d1)].first++;

        } else {

            g[P(d1, d0)].second++;

        }

    }



    int ans = 0;

    for (auto p: g) {

        ans += max(p.second.first, p.second.second);

    }

    cout << ans + (one ? 1 : 0) << endl;

    return 0;

}


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

#include <cstdio>

#include <cassert>

#include <cstring>

#include <vector>

#include <valarray>

#include <array>

#include <queue>

#include <set>

#include <unordered_set>

#include <map>

#include <unordered_map>

#include <algorithm>

#include <cmath>

#include <complex>

#include <random>



using namespace std;

using ll = long long;

using ull = unsigned long long;

template<class T = ll> constexpr T TEN(int n) {return (n==0)?1:10*TEN<T>(n-1);}



const int MP = 100100;

vector<int> pr;

vector<ull> bpr;



void first() {

    bool used[MP] = {};

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

        if (used[i]) continue;

        pr.push_back(i);

        ull x = ((__int128(1)<<64) + i-1 ) / i;

        bpr.push_back(x);

        for (int j = 2*i; j < MP; j += i) {

            used[j] = true;

        }

    }

}



map<ll, int> fact(ll n) {

    int pc = (int)pr.size();

    map<ll, int> mp;

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

        ll d = pr[i]; ull rd = bpr[i];

        if (n < d*d) break;

        while (true) {

            ll nd = __int128(n)*rd >> 64;

            if (nd * d != n) break;

            n = nd;

            mp[d]++;

        }

    }

    if (n > 1) mp[n]++;

    return mp;

}



ll mul(ll a, ll b) {

    if (TEN(12)/a < b) return TEN(12);

    return a*b;

}



int main() {

    first();

    using P = pair<ll, ll>;

    map<P, P> g;

    int n;

    scanf("%d", &n);

    bool one = false;

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

        if (i % 1000 == 0) {

//            cout << i << " " << gc << endl;

        }

        ll s;

        scanf("%lld", &s);

        map<ll, int> fac = fact(s);

        ll d0 = 1, d1 = 1;

        for (auto p: fac) {

            p.second %= 3;

            if (p.second == 1) {

                d0 = mul(d0, p.first);

                d1 = mul(d1, p.first);

                d1 = mul(d1, p.first);

            } else if (p.second == 2) {

                d0 = mul(d0, p.first);

                d0 = mul(d0, p.first);

                d1 = mul(d1, p.first);

            }

        }

        if (d0 == 1) {

            one = true;

            continue;

        }

        if (d0 < d1) {

            g[P(d0, d1)].first++;

        } else {

            g[P(d1, d0)].second++;

        }

    }



    int ans = 0;

    for (auto p: g) {

        ans += max(p.second.first, p.second.second);

    }

    cout << ans + (one ? 1 : 0) << endl;

    return 0;

}