#include <bits/stdc++.h>
#define fi first
#define se second
#define rep(i,n) for(int i = 0; i < (n); ++i)
#define rrep(i,n) for(int i = 1; i <= (n); ++i)
#define drep(i,n) for(int i = (n)-1; i >= 0; --i)
#define gep(i,g,j) for(int i = g.head[j]; i != -1; i = g.e[i].next)
#define each(it,c) for(__typeof((c).begin()) it=(c).begin();it!=(c).end();it++)
#define rng(a) a.begin(),a.end()
#define maxs(x,y) x = max(x,y)
#define mins(x,y) x = min(x,y)
#define pb push_back
#define sz(x) (int)(x).size()
#define pcnt __builtin_popcount
#define uni(x) x.erase(unique(rng(x)),x.end())
#define snuke srand((unsigned)clock()+(unsigned)time(NULL));
#define df(x) int x = in()
#define dame { puts("0"); return 0;}
#define show(x) cout<<#x<<" = "<<x<<endl;
using namespace std;
typedef long long int ll;
typedef pair<int,int> P;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vl;
typedef vector<P> vp;
template<typename T>istream& operator>>(istream&i,vector<T>&v)
{rep(j,sz(v))i>>v[j];return i;}
template<typename T>string join(vector<T>&v)
{stringstream s;rep(i,sz(v))s<<' '<<v[i];return s.str().substr(1);}
template<typename T>ostream& operator<<(ostream&o,vector<T>&v)
{if(sz(v))o<<join(v);return o;}
template<typename T1,typename T2>istream& operator>>(istream&i,pair<T1,T2>&v)
{return i>>v.fi>>v.se;}
template<typename T1,typename T2>ostream& operator<<(ostream&o,pair<T1,T2>&v)
{return o<<v.fi<<","<<v.se;}

const int MX = 100005, INF = 1001001001;
const ll LINF = 1e11;
const double eps = 1e-10;

vl bs, cs;

int fb(ll x) {
  int i = lower_bound(rng(bs),x)-bs.begin();
  if (bs[i] == x) return i;
  return 0;
}
// int fc(ll x) {
//   int i = lower_bound(rng(cs),x)-cs.begin();
//   if (cs[i] == x) return i;
//   return 0;
// }

// linear sieve
vi ps, pf;
void sieve(int mx) {
  pf = vi(mx);
  rep(i,mx) pf[i] = i;
  for (int i = 2; i < mx; ++i) {
    if (pf[i] == i) ps.pb(i);
    for (int j = 0; j < sz(ps) && ps[j] <= pf[i]; ++j) {
      int x = ps[j]*i;
      if (x >= mx) break;
      pf[x] = ps[j];
    }
  }
}
inline bool isp(int x) { return pf[x] == x && x >= 2;}
//

int main() {
  int n;
  scanf("%d",&n);
  vl a(n);
  rep(i,n) scanf("%lld",&a[i]);
  sort(rng(a));
  // vi b(n), c(n);
  rep(i,MX) {
    bs.pb((ll)i*i);
    // cs.pb((ll)i*i*i);
  }
  sieve(2222);
  map<ll,int> mp;
  map<ll,ll> dp;
  rep(i,n) {
    ll x = a[i];
    ll d = 1, e = 1;
    for (int p : ps) {
      int cnt = 0;
      while (x%p == 0) ++cnt, x /= p;
      cnt %= 3;
      if (cnt) {
        d *= p;
        if (e > LINF || e == -1) e = -1;
        else e *= p;
        if (cnt == 2) d *= p; else {
          if (e > LINF || e == -1) e = -1;
          else e *= p;
        }
      }
    }
    if (x != 1) {
      ll b = fb(x);
      if (b) {
        d *= x;
        if (e > LINF || e == -1) e = -1;
        else e *= b;
      } else {
        d *= x;
        if (e > LINF || e == -1) e = -1;
        else e *= x;
        if (e > LINF || e == -1) e = -1;
        else e *= x;
      }
    }
    dp[d] = e;
    mp[d]++;
  }
  int ans = 0;
  for (auto p : mp) {
    ll d = p.fi; int c = p.se;
    if (!c) continue;
    if (d == 1) ans++;
    else {
      ll e = dp[d];
      if (mp.count(e)) {
        maxs(c,mp[e]);
        mp[e] = 0;
      }
      mp[d] = 0;
      ans += c;
    }
  }
  cout<<ans<<endl;
  return 0;
}










Measured memory_bytes: 14324