1+ #include < bits/stdc++.h>
2+ using namespace std ;
3+
4+ #pragma GCC optimize("O3,unroll-loops")
5+ #pragma GCC target("avx2")
6+
7+ #define ll long long
8+ #define ull unsigned long long
9+ #define ld long double
10+ #define pb push_back
11+ #define mp make_pair
12+ #define f first
13+ #define s second
14+ #define all (x ) x.begin(), x.end()
15+ #define rep (i,a,b ) for (int i = a; i < b; ++i)
16+ #define rrep (i,a,b ) for (int i = a; i >= b; --i)
17+ #define in (a,n ) rep(i,0 ,n) cin>>a[i]
18+ #define yes cout<<" YES\n "
19+ #define no cout<<" NO\n "
20+ #define int long long
21+
22+ typedef vector<int > vi;
23+ typedef vector<ll> vl;
24+ typedef pair<int ,int > pi;
25+ typedef pair<ll,ll> pl;
26+ typedef vector<pi> vpi;
27+ typedef vector<pl> vpl;
28+
29+ const ll MOD = 1e9 + 7 ;
30+ const ll INF = 1e18 ;
31+ const int N = 2e5 + 5 ;
32+
33+ ll gcd (ll a, ll b) {
34+ while (b) a %= b, swap (a, b);
35+ return a;
36+ }
37+
38+ ll lcm (ll a, ll b) {
39+ return a / gcd (a, b) * b;
40+ }
41+
42+ ll power (ll a, ll b, ll mod = MOD) {
43+ ll res = 1 ; a %= mod;
44+ while (b > 0 ) {
45+ if (b & 1 ) res = res * a % mod;
46+ a = a * a % mod;
47+ b >>= 1 ;
48+ }
49+ return res;
50+ }
51+
52+ ll invmod (ll a, ll mod = MOD) {
53+ return power (a, mod - 2 , mod);
54+ }
55+
56+ ll fact[N], invfact[N];
57+ void precompute () {
58+ fact[0 ] = invfact[0 ] = 1 ;
59+ rep (i,1 ,N) fact[i] = fact[i-1 ]*i % MOD;
60+ invfact[N-1 ] = invmod (fact[N-1 ]);
61+ rrep (i,N-2 ,1 ) invfact[i] = invfact[i+1 ]*(i+1 ) % MOD;
62+ }
63+
64+ ll nCr (int n, int r) {
65+ if (r > n || r < 0 ) return 0 ;
66+ return fact[n] * invfact[r] % MOD * invfact[n - r] % MOD;
67+ }
68+
69+ vector<bool > is_prime;
70+ vi primes;
71+ void sieve (int maxn = N) {
72+ is_prime.assign (maxn + 1 , true );
73+ is_prime[0 ] = is_prime[1 ] = false ;
74+ for (int i = 2 ; i * i <= maxn; ++i) {
75+ if (is_prime[i]) {
76+ for (int j = i * i; j <= maxn; j += i)
77+ is_prime[j] = false ;
78+ }
79+ }
80+ rep (i, 2 , maxn + 1 ) if (is_prime[i]) primes.pb (i);
81+ }
82+ tuple<ll, int , int > kadane_with_indices (const vl &a) {
83+ ll max_sum = a[0 ], cur = a[0 ];
84+ int start = 0 , end = 0 , temp_start = 0 ;
85+
86+ rep (i, 1 , a.size ()) {
87+ if (a[i] > cur + a[i]) {
88+ cur = a[i];
89+ temp_start = i;
90+ } else {
91+ cur += a[i];
92+ }
93+
94+ if (cur > max_sum) {
95+ max_sum = cur;
96+ start = temp_start;
97+ end = i;
98+ }
99+ if (cur == 0 ) {
100+ temp_start = i + 1 ;
101+ }
102+ }
103+
104+ return {max_sum, start, end};
105+ }
106+
107+ // Disjoint Set Union (DSU)
108+ struct DSU {
109+ vi parent, size;
110+ DSU (int n) {
111+ parent.resize (n);
112+ size.assign (n, 1 );
113+ iota (all (parent), 0 );
114+ }
115+
116+ int find (int x) {
117+ return x == parent[x] ? x : parent[x] = find (parent[x]);
118+ }
119+
120+ bool unite (int x, int y) {
121+ x = find (x); y = find (y);
122+ if (x == y) return false ;
123+ if (size[x] < size[y]) swap (x, y);
124+ parent[y] = x;
125+ size[x] += size[y];
126+ return true ;
127+ }
128+ };
129+
130+ // Grid Traversal (4 & 8 directions)
131+ int dx[4 ] = {0 , 0 , 1 , -1 };
132+ int dy[4 ] = {1 , -1 , 0 , 0 };
133+ int ddx[8 ] = {0 ,0 ,1 ,-1 ,1 ,-1 ,1 ,-1 };
134+ int ddy[8 ] = {1 ,-1 ,0 ,0 ,1 ,-1 ,-1 ,1 };
135+
136+ bool DEBUG = true ;
137+ #define debug (x ) if (DEBUG) cout << " [DEBUG] " << #x << " = " << (x) << endl
138+
139+
140+ #undef int
141+ #include < ext/pb_ds/assoc_container.hpp>
142+ #include < ext/pb_ds/tree_policy.hpp>
143+ #define int long long
144+
145+ using namespace __gnu_pbds ;
146+ template <typename T>
147+ using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
148+
149+ // Functions:
150+ // s.find_by_order(k) ? k-th element
151+ // s.order_of_key(x) ? number of elements < x
152+
153+
154+ template <typename T>
155+ ostream& operator <<(ostream& os, const vector<T>& v) {
156+ for (int i = 0 ; i < (int )v.size (); i++) {
157+ if (i) os << " " ;
158+ os << v[i];
159+ }
160+ return os;
161+ }
162+ template <typename T>
163+ istream& operator >>(istream &is, vector<T> &v) {
164+ for (auto &x : v) is >> x;
165+ return is;
166+ }
167+ template <typename K, typename V>
168+ ostream& operator <<(ostream &os, const map<K,V> &mp) {
169+ os << " { " ;
170+ for (auto &p : mp) {
171+ os << p.first << " :" << p.second << " " ;
172+ }
173+ os << " }" ;
174+ return os;
175+ }
176+ #define debug (x ) if (DEBUG){ cout << " [DEBUG] " << #x << " = " ; cout << (x) << endl; }
177+
178+
179+ int mex (vector<int >& v) { // minimum excluded value
180+ unordered_set<int > s (v.begin (), v.end ());
181+ int m = 0 ;
182+ while (s.count (m)) m++;
183+ return m;
184+ }
185+
186+ int setbit (int n, int pos) { return n | (1LL << pos); }
187+ int unsetbit (int n, int pos) { return n & ~(1LL << pos); }
188+ int togglebit (int n, int pos) { return n ^ (1LL << pos); }
189+ bool checkbit (int n, int pos) { return n & (1LL << pos); }
190+
191+ // Count set bits
192+ int count_bits (int n) { return __builtin_popcountll (n); }
193+
194+ // Index of LSB/MSB
195+ int lsb (int n) { return __builtin_ctzll (n); } // least significant set bit index
196+ int msb (int n) { return 63 - __builtin_clzll (n); } // most significant set bit index
197+
198+
199+ long long sumOfDigits (long long n) {
200+ if (n < 10 ) return n * (n + 1 ) / 2 ; // direct sum
201+
202+ long long d = log10 (n); // number of digits - 1
203+ long long p = pow (10 , d); // largest power of 10 <= n
204+ long long msd = n / p; // most significant digit
205+
206+ // formula:
207+ // sum of digits from 1..n =
208+ // (msd * sumOfDigits(p-1)) [complete blocks before]
209+ // + (msd * (msd - 1) / 2) * p [contribution of MSD itself]
210+ // + (msd * (1 + n % p)) [MSD contribution in current block]
211+ // + sumOfDigits(n % p) [recurse on remaining suffix]
212+
213+ return (msd * sumOfDigits (p - 1 )) +
214+ (msd * (msd - 1 ) / 2 ) * p +
215+ (msd * (1 + n % p)) +
216+ sumOfDigits (n % p);
217+ }
218+
219+ vector<long long > digitCount (long long n) {
220+ vector<long long > cnt (10 , 0 );
221+ for (long long pos = 1 ; pos <= n; pos *= 10 ) {
222+ long long higher = n / (pos * 10 );
223+ long long cur = (n / pos) % 10 ;
224+ long long lower = n % pos;
225+
226+ // count for each digit
227+ for (int d = 0 ; d <= 9 ; d++) {
228+ cnt[d] += higher * pos; // full cycles
229+
230+ if (d < cur) cnt[d] += pos;
231+ else if (d == cur) cnt[d] += lower + 1 ;
232+ }
233+
234+ // fix leading zero problem
235+ cnt[0 ] -= pos;
236+ }
237+ return cnt;
238+ }
239+
240+ vector<int > prime_factors (int n) {
241+ vector<int > factors;
242+ for (int i = 2 ; i * i <= n; i++) {
243+ while (n % i == 0 ) {
244+ factors.pb (i);
245+ n /= i;
246+ }
247+ }
248+ if (n > 1 ) factors.pb (n);
249+ return factors;
250+ }
251+ vector<int > divisors (int n) {
252+ vector<int > divs;
253+ for (int i = 1 ; i * i <= n; i++) {
254+ if (n % i == 0 ) {
255+ divs.pb (i);
256+ if (i != n / i)
257+ divs.pb (n / i);
258+ }
259+ }
260+ sort (all (divs));
261+ return divs;
262+ }
263+ // Graph Utilities
264+ // --------------------------
265+ vector<vector<int >> adj;
266+ vector<int > vis;
267+
268+ void dfs (int u) {
269+ vis[u] = 1 ;
270+ for (auto v : adj[u]) {
271+ if (!vis[v]) dfs (v);
272+ }
273+ }
274+
275+ vector<int > bfs (int start, int n) {
276+ vector<int > dist (n+1 , -1 );
277+ queue<int > q;
278+ q.push (start);
279+ dist[start] = 0 ;
280+ while (!q.empty ()) {
281+ int u = q.front (); q.pop ();
282+ for (auto v : adj[u]) {
283+ if (dist[v] == -1 ) {
284+ dist[v] = dist[u] + 1 ;
285+ q.push (v);
286+ }
287+ }
288+ }
289+ return dist;
290+ }
291+
292+
293+ long long nextNonDividingPrime (long long n) {
294+ // Small primes list (enough for all practical n ? 1e18)
295+ static const int primes[] = {
296+ 2 , 3 , 5 , 7 , 11 , 13 , 17 , 19 , 23 , 29 ,
297+ 31 , 37 , 41 , 43 , 47 , 53 , 59 , 61 , 67 ,
298+ 71 , 73 , 79 , 83 , 89 , 97
299+ };
300+
301+ for (int p : primes) {
302+ if (n % p != 0 )
303+ return p; // found the smallest prime not dividing n
304+ }
305+
306+ // In the (practically impossible) case n is divisible by all above,
307+ // find the next prime manually
308+ auto isPrime = [](long long x) {
309+ if (x < 2 ) return false ;
310+ for (long long i = 2 ; i * i <= x; i++)
311+ if (x % i == 0 ) return false ;
312+ return true ;
313+ };
314+
315+ long long candidate = 101 ; // next after our list
316+ while (true ) {
317+ if (isPrime (candidate) && n % candidate != 0 )
318+ return candidate;
319+ candidate++;
320+ }
321+ }
322+
323+
324+ // *********************************************************************************//
325+
326+
327+ vector<pair<int ,int >> tomap (int a, int k){
328+ vector<pair<int ,int >> key;
329+ for (ll i = 2 ; i * i <= a; i++) {
330+ if (a % i == 0 ){
331+ int cnt = 0 ;
332+ while (a % i == 0 ) {
333+ a /= i;
334+ cnt++;
335+ }
336+ cnt %= k;
337+ if (cnt != 0 )
338+ key.pb ({(int )i, cnt});
339+ }
340+ }
341+ if (a > 1 ){
342+ key.pb ({(int )a, 1 % k});
343+ }
344+ return key;
345+ }
346+
347+ vector<pair<int ,int >> need (const vector<pair<int ,int >>& key, int k){
348+ vector<pair<int ,int >> res;
349+ for (auto [p, r] : key){
350+ res.pb ({p, (k - r) % k});
351+ }
352+ return res;
353+ }
354+
355+ void solve () {
356+ int n, k;
357+ cin >> n >> k;
358+ vector<ll> v (n);
359+ in (v, n);
360+ int ans = 0 ;
361+ map<vector<pair<int ,int >>, int > freq;
362+ for (int i = 0 ; i < n; i++){
363+ auto cur = tomap (v[i], k);
364+ auto rem = need (cur, k);
365+ ans += freq[rem];
366+ freq[cur]++;
367+ }
368+ cout << ans << " \n " ;
369+ }
370+
371+
372+ signed main () {
373+ ios::sync_with_stdio (false );
374+ cin.tie (nullptr ); cout.tie (nullptr );
375+
376+ // precompute();
377+ // sieve();
378+ DEBUG = false ;
379+ // ll t;
380+ // cin >> t;
381+ // while (t--) {
382+ solve ();
383+ // }
384+ return 0 ;
385+ }
0 commit comments