Problem:
Score : 1100 points

Problem Statement

Snuke got positive integers s_1,...,s_N from his mother, as a birthday present. There may be duplicate elements.

He will circle some of these N integers. Since he dislikes cubic numbers, he wants to ensure that if both s_i and s_j (i ≠ j) are circled, the product s_is_j is not cubic. For example, when s_1=1,s_2=1,s_3=2,s_4=4, it is not possible to circle both s_1 and s_2 at the same time. It is not possible to circle both s_3 and s_4 at the same time, either.

Find the maximum number of integers that Snuke can circle.

Constraints

1 ≦ N ≦ 10^5

1 ≦ s_i ≦ 10^{10}

All input values are integers.

Input

The input is given from Standard Input in the following format:

N
s_1
:
s_N

Output

Print the maximum number of integers that Snuke can circle.

Sample Input 1

8
1
2
3
4
5
6
7
8

Sample Output 1

6

Snuke can circle 1,2,3,5,6,7.

Sample Input 2

6
2
4
8
16
32
64

Sample Output 2

3

Sample Input 3

10
1
10
100
1000000007
10000000000
1000000009
999999999
999
999
999

Sample Output 3

9

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

#include <bits/stdc++.h>
#define N 100020
#define ll long long
using namespace std;
inline ll read(){
  ll x=0,f=1;char ch=getchar();
  while(ch>'9'||ch<'0')ch=='-'&&(f=0)||(ch=getchar());
  while(ch<='9'&&ch>='0')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
  return f?x:-x;
}
map<ll, int> cnt, vis;
ll a[N], cub[N];
const ll MAX_CUB = 2154;
bool mark[MAX_CUB + 20];
int prime[MAX_CUB + 20], tot;
void filter_prime(int size) {
  for (int i = 2; i <= size; ++ i) {
    if (!mark[i]) prime[++ tot] = i;
    for (int j = 1; j <= size && prime[j] * i <= size; ++ j) {
      mark[prime[j] * i] = 1;
      if (i % prime[j] == 0) {
        break;
      }
    }
  }
}
bool isSquare(ll x) {
  ll k = sqrt(x);
  return k * k == x;
}
ll calc(ll x) {
  ll rev = 1;
  for (int i = 1; i <= tot; ++ i) {
    int c = 0;
    while (x % prime[i] == 0) {
      x /= prime[i];
      ++ c;
    }
    if (c) {
      for (; c < 3; ++ c) {
        rev *= prime[i];
      }
    }
  }
  // 此时 x 要么是质数，要么是平方数
  if (isSquare(x)) {
    rev *= sqrt(x);
  } else {
    rev *= x * x;
  }
  return rev;
}
int main(int argc, char const *argv[]) {
  // freopen("../../temp/test.in", "r", stdin);
  filter_prime(MAX_CUB);
  int n = read();
  for (int i = 2; i <= MAX_CUB; ++ i) {
    cub[i] = (ll) i * i * i;
  }
  for (int i = 1; i <= n; ++ i) {
    a[i] = read();
    for (int j = 2; j <= MAX_CUB; ++ j) {
      while (a[i] % cub[j] == 0) {
        a[i] /= cub[j];
      }
    }
    ++ cnt[a[i]];
  }
  cnt[1] = min(cnt[1], 1);
  int ans = 0;
  for (int i = 1; i <= n; ++ i) {
    if (vis[a[i]]) {
      continue;
    }
    vis[a[i]] = 1;
    ll rev = calc(a[i]);
    vis[rev] = 1;
    ans += max(cnt[a[i]], cnt[rev]);
  }
  printf("%d\n", ans);
  return 0;
}
/*

首先发现将每个数的立方因子筛去对答案不会有影响。

于是对每个数使其质因子的指数都 mod 3

可以发现能与每个数相乘是立方数的数只有 1 个，这里定义其为该数的补数。

对于每个数和它的补数，将出现次数较多的计入答案。

只需要考虑如何计算补数即可。

*/