「luogu3704」[SDOI2017]数字表格
莫比乌斯反演,其中一些处理比较套路
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int N=1000010,mod=1000000007; 5 ll n,m,u[N],f[N],fi[N],invfi[N]; 6 int p[N],tot,lim=1000000; 7 bool isp[N]; 8 ll qpow(ll x,ll y){ 9 ll res=1; 10 while(y){ 11 if(y&1) res=res*x%mod; 12 x=x*x%mod,y>>=1; 13 } 14 return res; 15 } 16 void pre(){ 17 f[0]=1,u[1]=1,fi[1]=1,invfi[1]=1,f[1]=1; 18 for(int i=2;i<=lim;i++){ 19 f[i]=fi[i]=(fi[i-1]+fi[i-2])%mod; 20 invfi[i]=qpow(fi[i],mod-2); 21 } 22 for(int i=2;i<=lim;i++){ 23 if(!isp[i]) p[++tot]=i,u[i]=-1; 24 for(int j=1;j<=tot&&1LL*i*p[j]<=lim;j++){ 25 isp[i*p[j]]=1; 26 if(i%p[j]) u[i*p[j]]=-u[i]; 27 else{u[i*p[j]]=0;break;} 28 } 29 if(u[i]) for(int j=1;j*i<=lim;j++) 30 f[i*j]=f[i*j]*(u[i]==1?fi[j]:invfi[j])%mod; 31 } 32 for(int i=2;i<=lim;i++) f[i]=f[i]*f[i-1]%mod; 33 return; 34 } 35 void solve(){ 36 scanf("%lld%lld",&n,&m); 37 if(n>m) swap(n,m); 38 ll l=1,r,res=1; 39 while(l<=n){ 40 r=min(n/(n/l),m/(m/l)); 41 ll temp=f[r]*qpow(f[l-1],mod-2)%mod; 42 res=res*qpow(temp,(n/l)*(m/l)%(mod-1))%mod; 43 l=r+1; 44 } 45 printf("%lld\n",res); 46 return; 47 } 48 int main(){ 49 pre(); 50 int T;scanf("%d",&T); 51 while(T--) solve(); 52 return 0; 53 }