2019-11-06
传送门::https://codeforces.com/contest/1247/problem/D
题意::有多少种组合方式满足乘积可以同x^k表示(k>=2)
思路::质因数分解,任何一个合数都可以拆成几个质因数之积;
对于一个数而言 拆解后可表示成 p1^k1 * p2^k2 * p3^k3······当k1,k2 ······满足为k的倍数时我们可以不用考虑,而对那些不为k的倍数的数我们是不是该想办法从其他数中找能配对成k的倍数的数,这样组合就存在了。
详情见代码::
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int maxn=1e5+5; 5 6 ll a[maxn],b[maxn]; 7 ll qpow(ll x,int p) 8 { 9 ll ans=1; 10 while(p){ 11 if(p&1){ans=ans*x;} 12 x=x*x; 13 p>>=1; 14 } 15 return ans; 16 } 17 map<ll,ll>mp; 18 int main() 19 { 20 int n,k; 21 scanf("%d%d",&n,&k); 22 for(ll i=1;i<=n;i++){ 23 scanf("%lld",&a[i]); 24 } 25 for(ll i=1;i<=n;i++){ 26 ll now=1,need=1; 27 for(ll j=2;j<=sqrt(a[i]);j++){//质因数分解 28 int ant=0; 29 if(a[i]%j==0){ 30 while(a[i]%j==0){ 31 a[i]/=j;ant++; 32 } 33 } 34 ant%=k; 35 now*=qpow(j,ant);//记录可用于弥补的值 36 if(ant!=0){need*=qpow(j,k-ant);}//不为k倍数时需要进行弥补的数 37 } 38 if(a[i]!=1){ 39 now*=a[i];need*=qpow(a[i],k-1);//同上 40 } 41 a[i]=now;b[i]=need; 42 mp[a[i]]++; 43 } 44 ll ans=0; 45 for(int i=1;i<=n;i++){ 46 if(a[i]==b[i]){ans+=mp[a[i]]-1;}//这种情况为本身就可以表示成x^k的形式 47 else{ans+=mp[b[i]];}//寻找弥补的数 48 } 49 printf("%lld\n",ans/2); 50 return 0; 51 }