题目链接:Click here
Solution:
先把原式写出来
[prod_{i=1}^n prod _{j=1}^m F_{gcd(i,j)}\
]
设(k=gcd(i,j)),假设(nle m)
[prod_{i=1}^n prod _{j=1}^m F_{t}\
prod_{k=1}^n F_k ^{(sum _{i=1} ^{lfloor frac{n}{k}
floor} sum _{j=1} ^{lfloor frac{m}{k}
floor} [gcd(i,j)=1])}
]
我们把指数提出了,发现是我们非常熟悉的形式
[sum _{i=1} ^{lfloor frac{n}{k}
floor} sum _{j=1} ^{lfloor frac{m}{k}
floor} [gcd(i,j)=1]\
sum _{i=1} ^{lfloor frac{n}{k}
floor} sum _{j=1} ^{lfloor frac{m}{k}
floor} sum _{t|i} sum_{t|j} mu(t)\
sum_{t=1}^{lfloor frac{n}{k}
floor} mu(t) lfloor frac{n}{kt}
floor lfloor frac{m}{kt}
floor
]
那么现在式子变成了这个形式
[prod_{k=1}^n F_k ^{(sum_{t=1}^{lfloor frac{n}{k}
floor} mu(t) lfloor frac{n}{kt}
floor lfloor frac{m}{kt}
floor)}
]
我们令(T=kt),然后枚举(T)
[prod _{T=1} ^n(sum_{k|T} F_k ^{mu({{T} over {}k})})^{lfloor frac{n}{T}
floor lfloor frac{m}{T}
floor}
]
我们设(f(n))
[f(n)=sum_{d|n} F_d ^{mu ({n over d})}
]
则原始为
[prod _{T=1} ^n f(T) ^{lfloor frac{n}{T}
floor lfloor frac{m}{T}
floor}
]
那么我们暴力预处理出(f(n))后数论分块即可
Code:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+11;
const int mod=1e9+7;
bool vis[N];
int n,m,u[N],p[N],f[N],g[N];
int ans,cnt,F[N],I[N];
int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
int qpow(int a,int b){
int re=1;
while(b){
if(b&1) re=re*a%mod;
b>>=1;a=a*a%mod;
}return re;
}
void prepare(){
u[1]=1;I[1]=F[1]=1;g[0]=g[1]=1;
for(int i=2;i<N;i++){
F[i]=(F[i-1]+F[i-2])%mod;
I[i]=qpow(F[i],mod-2);
if(!vis[i]) p[++cnt]=i,u[i]=-1;
for(int j=1;j<=cnt&&i*p[j]<N;j++){
vis[i*p[j]]=1;
if(i%p[j]==0) break;
u[i*p[j]]=-u[i];
}
}
for(int i=1;i<N;i++) f[i]=1;
for(int i=1;i<N;i++){
if(!u[i]) continue;
for(int j=i;j<N;j+=i)
f[j]=f[j]*(u[i]==1?F[j/i]:I[j/i])%mod;
}
for(int i=2;i<N;i++) f[i]=f[i]*f[i-1]%mod;
for(int i=2;i<N;i++) g[i]=qpow(f[i],mod-2);
}
void solve(){
n=read(),m=read();
ans=1;if(n>m) swap(n,m);
for(int i=1,j;i<=n;i=j+1){
j=min(n/(n/i),m/(m/i));
int val=f[j]*g[i-1]%mod;
ans=ans*qpow(val,(n/i)*(m/i))%mod;
}
printf("%lld
",ans%mod);
}
signed main(){
prepare();
int t=read();
while(t--) solve();
return 0;
}