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 }
12-27 18:05