【题解】[SDOI2017]数字表格
#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\)时没有想到,于是悲惨爆零)
注意函数的筛法,以及指数取余的时候可以套用欧拉定理。