给定一个长度为 n 的正整数数列 a1,a2,…,an 和一个正整数 kk。
请你判断共有多少个数对 (l,r) 同时满足:
- 1≤l<r≤n
- 存在一个整数 x 使得 al×ar=xk 成立
输入格式
第一行包含两个整数 n,k。
第二行包含 n 个正整数 a1,a2,…,an。
输出格式
一个整数,表示满足条件的数对的数量。
数据范围
前三个测试点满足 2≤n≤10。
所有测试点满足 2≤n≤105,2≤k≤100,1≤ai≤1055。
输入样例:
6 3
1 3 9 8 24 1
输出样例:
5
分析:解析在注释里
代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5+10;
int n, k,num;
LL p, con_p, ans;
int cnt[N];
LL power(int x, int s)
{
LL res = 1; //不用LL会爆int
while(s--)
{
res *= x;
if(res >= N) //如果结果大于N(不满足题意),说明没有意义
{
res = 0;
break;
}
}
return res;
}
int main()
{
cin>>n>>k;
for(int i = 0; i < n; i++)
{
cin>>num;
p = 1, con_p = 1;
for(int i = 2; i*i <= num; i++) //先分解因式
{
if(num%i == 0) //若i是num的因子
{
int s = 0; //i的阶数
while(num%i == 0) //求i的阶数
{
s++;
num /= i;
}
s %= k; //我们需要的是s除以k的余数
if(s)
{
p *= power(i, s); //不会大于N,因为p是num的因子,而num < N
con_p *= power(i, k-s); //若太大则没意义,会返回0
}
}
}
if(num > 1) //因式分解后还是大于1,说明是质数
{
p *= num;
con_p *= power(num, k-1);
}
if(con_p >= N) //若是“互补”的数大于n,则没有意义
con_p = 0;
ans += cnt[con_p];
cnt[p]++;
}
cout<<ans;
return 0;
}