P13732 【MGVOI R1-D】图上的数(graph)
由算术基本定理,令
则
于是第一问可以在
显然也可以通过预处理做到
对于第二问,考虑分别计数
接下来是非常简单的推式子。虽然看起来有一些恐怖。
时间复杂度
:::success[【MGVOI R1-D】图上的数 - graph.cpp]
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=20;
const int mod=1e9+7;
int cnt[maxn],p[maxn];
inline int qkpow(int a,int p){
int res=1;
while(p){
if(p&1) res=1ll*res*a%mod;
a=1ll*a*a%mod,p>>=1;
}
return res;
}
inline int sol(int n,int m){
ll res=0;
int val=1,inv=qkpow(n-1,mod-2);
int invn=qkpow(n,mod-2),pw=qkpow(n,m+1);
for(int i=0;i<=m;i++){
if(i){
val=1ll*val*i%mod*n%mod*n%mod;
pw=1ll*pw*invn%mod;
}
res+=1ll*val*(pw+mod-1)%mod*inv%mod;
}
res%=mod;
return res;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int t;cin>>t;
while(t--){
int a,b,k=0;
cin>>a>>b;
int cura=a;
for(int i=2;i<=sqrt(a);i++){
if(a%i) continue;
p[++k]=i,cnt[k]=0;
while(a%i==0) cnt[k]+=b,a/=i;
}
if(a>1) p[++k]=a,cnt[k]=b;
int ans0=1,ans1=1,ans2=1,ljd=qkpow(cura,b);
ljd=1ll*ljd*ljd%mod;
for(int i=1;i<=k;i++){
for(int j=1;j<=cnt[i];j++) ans0=1ll*ans0*j%mod;
ans1=1ll*ans1*sol(p[i],cnt[i])%mod;
ans2=1ll*ans2*(1ll*(cnt[i]+1)*(cnt[i]+2)/2%mod)%mod;
}
ans1=(ans1+ljd-ans2);
ans1=(ans1%mod+mod)%mod;
cout<<ans0<<" "<<ans1<<"\n";
}
return 0;
}
:::