【題解】[SDOI2017]數字表格
阿新 • • 發佈:2020-07-24
#include<bits/stdc++.h> using namespace std; #define int long long const int MAXN=1e6; int T,n,m,f[MAXN+10],g[MAXN+10],inv[MAXN+10]; const int mod=1e9+7; inline int add(int x,int y){return (x+y+mod)%mod;} inline int mul(int x,int y){return 1ll*x*y%mod;} inline int mul_(int x,int y){return 1ll*x*y%(mod-1);} bitset<MAXN+10>vis; int p[MAXN+10],cnt,mu[MAXN+10],ans; inline int qpow(int x,int y){ int res=1; while(y){ if(y&1)res=mul(res,x); x=mul(x,x);y>>=1; } return res; } void pretreatment(int G){ mu[1]=1;f[1]=1;inv[1]=1;g[0]=g[1]=1;vis[1]=1; for(int i=2;i<=G;++i){ f[i]=f[i-1]+f[i-2];f[i]%=mod; inv[i]=qpow(f[i],mod-2);g[i]=1; if(!vis[i])p[++cnt]=i,mu[i]=-1; for(int j=1;j<=cnt&&i*p[j]<=G;++j){ vis[i*p[j]]=1; if(i%p[j]==0)break; mu[i*p[j]]=-mu[i]; } } //for(int i=1;i<=G;++i)mu[i]+=mu[i-1]; for(int i=1;i<=G;++i){ if(!mu[i])continue; for(int j=i;j<=G;j+=i){ g[j]=1ll*g[j]*(mu[i]==1?f[j/i]:inv[j/i])%mod; } } for(int i=2;i<=G;++i)g[i]=mul(g[i],g[i-1]); } int solve(int N,int M){ int res=1; for(int l=1,r;l<=min(N,M);l=r+1){ r=min(N/(N/l),M/(M/l)); int PP=mul(g[r],qpow(g[l-1],mod-2)); res=mul(res,qpow(PP,mul_(N/l,M/l))); } return res; } signed main(){ //freopen("1.in","r",stdin); //freopen("test.out","w",stdout); pretreatment(1000000); scanf("%lld",&T); while(T--){ scanf("%lld%lld",&n,&m); if(n>m)swap(n,m); ans=solve(n,m); printf("%lld\n",(ans+mod)%mod); } return 0; }
菜雞筆者推到列舉\(kd\)時沒有想到,於是悲慘爆零)
注意函式的篩法,以及指數取餘的時候可以套用尤拉定理。