传送门
说下题意,给1e5个数和一个K,求里面两个数之积为x的k次方有多少组,x为任意值。
解题思路:首先根据算术基本定理对于,对每一个数进行质因数分解a=p1e1+p2e2+…+pnen,因为两个数之积为一个值的k次方,那么这两个数的每一个质因数的次方之和一定为k的倍数。然后计算贡献,每一个值对于后面的贡献是每一个质因数的次数对k取模后的积,同时计算这个值还缺多少个数字变成k次方,加上这个值在前面贡献的次数——(他乘以前面的值为k次方的个数)。
#include<stdio.h>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 1e5+5;
int vis[N],pri[N][2],len,a[N];
void prime(int x)//质因数分解
{
len=0;
int i;
for(i=2;i*i<=x;i++)
if(x%i==0)
{
pri[++len][0]=i;
pri[len][1]=0;//初始化
while(x%i==0)
pri[len][1]++,x/=i;
}
if(x!=1)
{
pri[++len][0]=x;
pri[len][1]=1;
}
}
int main()
{
int n,m,i,j,k;
scanf("%d %d",&n,&m);
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
ll x,x1=1,y,y1=1,ans=0;
for(i=1;i<=n;i++)
{
x1=1,y1=1;
prime(a[i]);
int flag1=0,flag2=0;
for(j=1;j<=len;j++)
{
x=(m-pri[j][1]%m)%m;//判断需要多少个此质数
y=pri[j][1]%m;
while(x--)
{
x1*=pri[j][0];该质数之积如果大于1e5则不需要计算(两个数都小于1e5,大于1e5一定不是答案)
if(x1>=N) flag2=1;
}
while(y--)
{
y1*=pri[j][0];
if(y1>=N) flag1=1;
}
}
if(!flag2) ans+=vis[x1];
if(!flag1) vis[y1]++;//加上y1的贡献
}
printf("%lld\n",ans);
}