题目大意
给出一个长度为
n
n
n的数组
a
1
,
a
2
,
⋯
,
a
n
a_1,a_2,\cdots,a_n
a1,a2,⋯,an,
问有多少对
(
i
,
j
)
,
i
<
j
\pod{i,j},i<j
(i,j),i<j满足
a
i
×
a
j
=
x
k
a_i\times a_j= x^k
ai×aj=xk,
x
x
x为任意整数。
时间限制
2s
数据范围
n
≤
1
0
5
n\le 10^5
n≤105
a
i
≤
1
0
5
a_i\le 10^5
ai≤105
题解
涉及到乘法,就应该考虑质因数,不妨先分解质因数。
如果要使得
a
i
×
a
j
=
x
k
a_i\times a_j= x^k
ai×aj=xk,则它们质因子的次幂均为
k
k
k的倍数。
于是就可以有这样应该结论
x
k
+
1
x^k+1
xk+1与
x
1
x^1
x1这此题中是等价的,
于是先可以分解质因数,然后先处理一下质因子的次幂,均对
k
k
k取模。
现在所有的数的次幂都不超过 k k k,那么现在要找到与它相乘满足条件的数,那么显然就是在质因子的次幂做文章。
而因为 a i a_i ai不大,可以用一个桶来储存。
Code
//#pragma GCC optimize (2)
//#pragma G++ optimize (2)
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
#include <vector>
#include <queue>
#define G getchar
#define ll long long
using namespace std;
ll read()
{
char ch;
for(ch = G();(ch < '0' || ch > '9') && ch != '-';ch = G());
ll n = 0 , w;
if (ch == '-')
{
w = -1;
ch = G();
} else w = 1;
for(;'0' <= ch && ch <= '9';ch = G())n = (n<<1)+(n<<3)+ch-48;
return n * w;
}
const int N = 200003;
ll n , ans , K , tmp;
ll pri[N] , k[N] , m;
int prime[66] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317};
int ss[16] = {2 , 3 , 5 , 7 , 11 ,13 , 17 , 19 , 23 , 29 , 325 , 9375 , 28187 , 450775 , 9870504 , 1795265022};
int s[N];
ll mul (ll a , ll b , ll p) //a*b%p
{
/*ll s = 0;
for ( ; b ; )
{
if (b & 1) s = (s + a) % p;
a = (a + a) % p;
b = b >> 1;
}
return s;*/
ll s = a * b - (ll)((long double) a * b / p +0.5) * p;
return s < 0 ? s + p : s;
}
ll ksm (ll x , ll y , ll p)
{
ll s = 1;
for ( ; y ; )
{
if (y & 1) s = mul(s , x , p);
x = mul (x , x , p);
y = y >> 1;
}
return s;
}
bool MR_detect (ll n , ll a)
{
if (n == a) return 1;
if (a % n == 0) return 1;
if (ksm(a , n - 1 , n) != 1) return 0;
ll p = n - 1 , lst = 1;
for ( ; ((p & 1) ^ 1) && lst == 1 ; )
{
p = p >> 1;
lst = ksm(a , p , n);
if (lst != 1 && lst != n - 1) return 0;
}
return 1;
}
bool MR(ll n)
{
if (n < 2) return 0;
for (int i = 0 ; i < 13 ; i ++)
if (! MR_detect(n , ss[i])) return 0;
return 1;
}
ll F(ll x , ll C , ll p)
{
return (mul(x , x , p) + C) % p;
}
ll gcd(ll a , ll b)
{
return a % b ? gcd(b , a % b) : b;
}
ll Rand()
{
return (ll)rand() + ((ll)rand() << 15) + ((ll)rand() << 30) + ((ll)rand() << 45);
}
ll PR(ll n)
{
if (MR(n)) return n;
if (n == 4) return 2;
for ( ; ; )
{
ll C = Rand() % (n - 1) + 1;
ll p1 = 0 , p2 = 0;
ll s = 1 , tmp;
for ( ; ; )
{
for (int i = 0 ; i < 128 ; i++)
{
p2 = F(F(p2 , C , n) , C , n);
p1 = F(p1 , C , n);
tmp = mul(s , abs(p1 - p2) , n);
if (tmp == 0 || p1 == p2) break;
s = tmp;
}
tmp = gcd(n , s);
if (tmp > 1) return tmp;
if (p1 == p2) break;
}
}
}
ll ksm1(ll x , int y)
{
ll s = 1;
for ( ; y && s < N && x < N ; )
{
if (y & 1) s = s * x;
x = x * x;
y = y >> 1;
}
//if ((x >= N && y > 0) || s > N ) return N ; else return s;
return s;
}
void work(ll n)
{
m = 0;
for (int i = 0 ; i < 66 ; i++)
{
if (n % prime[i] == 0)
{
m++;
tmp = prime[i];
pri[m] = tmp;
k[m] = 0;
for ( ; n % tmp == 0 ; )
{
k[m]++;
n = n / tmp;
}
}
}
if (n > 1)
{
m++;
k[m] = 1;
pri[m] = n;
}
/*for ( ; n != 1 ; )
{
ll tmp = PR(n);
for ( ; !MR(tmp) ; )tmp = PR(tmp);
m++;
pri[m] = tmp;
k[m] = 0;
for ( ; n % tmp == 0 ; )
{
k[m]++;
n = n / tmp;
}
}*/
ll tmp = 1;
n = 1;
for (int i = 1 ; i <= m ; i++)
{
k[i] = k[i] % K;
if (k[i] == 0) continue;
for (int j = 1 ; j <= k[i] ; j++)
n = n * pri[i];
for (int j = 1 ; j <= K - k[i] ; j++)
{
tmp = tmp * pri[i];
if (tmp > 100000) break;
}
//n = n * ksm1(pri[i] , k[i]);
//if (tmp < N) tmp = tmp * ksm1(pri[i] , K - k[i]);
}
if (tmp < N) ans = ans + s[tmp];
s[n]++;
}
int main()
{
//freopen("h.in","r",stdin);
//freopen("2.txt","w",stdout);
srand((unsigned)3);
n = read();
K = read();
ans = 0;
for (int i = 1 ; i <= n ; i++)
{
tmp = read();
work(tmp);
}
printf("%lld\n", ans);
return 0;
}