#include <bits/stdc++.h>
using namespace std;
template <class e, class t, int N>
std::basic_istream<e, t>& operator>>(std::basic_istream<e, t>& in,
                                     const e (&literal)[N]) {
  std::array<e, N - 1> buffer;
  in >> buffer[0];
  if (N > 2) in.read(&buffer[1], N - 2);
  if (strncmp(&buffer[0], literal, N - 1))
    in.setstate(in.rdstate() | std::ios::badbit);
  return in;
}
template <class e, class t>
std::basic_istream<e, t>& operator>>(std::basic_istream<e, t>& in,
                                     const e& literal) {
  e buffer;
  in >> buffer;
  if (buffer != literal) in.setstate(in.rdstate() | std::ios::badbit);
  return in;
}
template <class e, class t, int N>
std::basic_istream<e, t>& operator>>(std::basic_istream<e, t>& in,
                                     e (&carray)[N]) {
  return std::operator>>(in, carray);
}
template <class t>
istream& operator>>(istream& in, vector<t>& v) {
  for (int i = 0; i < v.size(); i++) in >> v[i];
  return in;
}
template <class t1, class t2>
istream& operator>>(istream& in, pair<t1, t2>& v) {
  cin >> v.first >> v.second;
  return in;
}
template <class t1, class t2>
ostream& operator<<(ostream& out, const pair<t1, t2>& a) {
  out << a.first << " " << a.second;
  return out;
}
template <class t>
ostream& operator<<(ostream& out, vector<t>& a) {
  for (auto x : a) {
    out << x << " ";
  }
  return out;
}
template <class t>
ostream& operator<<(ostream& out, set<t>& a) {
  for (auto x : a) {
    out << x << " ";
  }
  return out;
}
template <class t>
ostream& operator<<(ostream& out, multiset<t>& a) {
  for (auto x : a) {
    out << x << " ";
  }
  return out;
}
template <class t1, class t2>
ostream& operator<<(ostream& out, map<t1, t2>& a) {
  for (auto x : a) {
    out << x.first << " = " << x.second << endl;
  }
  return out;
}
template <class t1, class t2>
pair<t1, t2> operator+(const pair<t2, t1>& a, const pair<t1, t2>& b) {
  return {a.first + b.first, a.second + b.second};
}
template <class t1, class t2>
pair<t1, t2> operator-(const pair<t2, t1>& a, const pair<t1, t2>& b) {
  return {a.first - b.first, a.second - b.second};
}
long long gcd(long long a, long long b) { return b == 0 ? a : gcd(b, a % b); }
long long lcm(long long a, long long b) { return a * (b / gcd(a, b)); }
long long fpow(long long b, long long e, long long m = (long long)(1e9 + 7)) {
  long long r = 1;
  while (e) {
    if (e & 1) r = (r * b) % m;
    e /= 2;
    b = (b * b) % m;
  }
  return r;
}
long long cr[100005];
void init_sieve() {
  memset(cr, -1, sizeof(cr));
  for (long long i = 2; i < (long long)100005; i++)
    if (cr[i] < 0)
      for (long long j = 1LL * i * i; j < 100005; j += i) cr[j] = i;
}
map<long long, long long> fact(long long n) {
  map<long long, long long> r;
  while (cr[n] >= 0) r[cr[n]]++, n /= cr[n];
  if (n > 1) r[n]++;
  r[1] = 0;
  return r;
}
int32_t main(int32_t argc, char const* argv[]) {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  ;
  init_sieve();
  long long n, k;
  cin >> n >> k;
  vector<long long> a(n);
  cin >> a;
  vector<pair<long long, long long> > p[n];
  map<vector<pair<long long, long long> >, long long> m;
  long long l = 0;
  for (long long i = 0; i < (long long)n; i++) {
    auto first = fact(a[i]);
    for (auto x : first) {
      if (x.second % k != 0) p[i].push_back({x.first, x.second % k});
    }
    if (((long long)(p[i]).size()) == 0)
      l++;
    else
      m[p[i]]++;
  }
  long long res = 0;
  for (long long i = 0; i < (long long)n; i++) {
    vector<pair<long long, long long> > r;
    for (auto x : p[i]) r.push_back({x.first, k - x.second});
    auto x = m.find(r);
    if (x != m.end()) {
      res += x->second - (x->first == p[i]);
    }
  }
  res += (l * (l - 1));
  cout << res / 2 << "\n";
  return 0;
}
