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: Time Limit Exceeded)

#define _USE_MATH_DEFINES
#include <cassert>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <queue>
#include <stack>
#include <list>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>
#include <complex>
#include <cmath>
#include <numeric>
#include <bitset>
#include <functional>

using namespace std;

#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
  cerr << name << ": " << arg1 << endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
  const char* comma = strchr(names + 1, ',');
  cerr.write(names, comma - names) << ": " << arg1 << " |";
  __f(comma + 1, args...);
}

typedef long long int64;
typedef pair<int, int> ii;
const int INF = 1 << 29;
const int MOD = 1e9 + 7;

const int N = 2e5;
bool flag[N];
vector<int> prime;

void gen_prime() {
  for (int i = 2; i < N; ++i) {
    if (flag[i]) continue;
    prime.push_back(i);
    for (int j = i + i; j < N; j += i) {
      flag[i] = true;
    }
  }
}

int main() {
  gen_prime();
  int n;
  scanf("%d", &n);
  map<int64, int64> A, B;
  int64 bound = 1e10;
  for (int i = 0; i < n; ++i) {
    int64 x, y;
    __int128 z;
    scanf("%lld", &x);
    y = z = 1;
    for (int i = 0; ; ++i) {
      int64 p = prime[i];
      if (p * p > x) break;
      if (x % p == 0) {
        int cnt = 0;
        while (x % p == 0) {
          x /= p;
          ++cnt;
        }
        cnt %= 3;
        if (cnt) {
          z *= (__int128)p * p * p;
          while (cnt--) {
            y *= p;
            z /= p;
          }
        }
      }
    }
    if (x > 1) {
      y *= x;
      z *= (__int128)x * x;
    }
    if (z < bound) {
      B[y] = z;
      B[z] = y;
    }
    A[y]++;
  }
  int ret = 0;
  for (auto& it : A) {
    int64 x = it.first;
    if (x == 1) {
      ret += 1;
    } else {
      int64 y = B[x];
      if (A.count(y)) {
        if (y > x) {
          ret += max(A[x], A[y]);
        }
      } else {
        ret += A[x];
      }
    }
  }
  printf("%d\n", ret);

  return 0;
}