这道题明显可以用莫比乌斯反演来做,非常的裸的繁衍。
假设n < m
ans=∏ni=1∏mj=1f[gcd(i,j)]
那么直接枚举gcd=d
ans=∏nd=1f[d]g[d]
g[d]表示gcd=d的个数
繁衍一下
g[d]=∑i|d⌊nd⌋⌊md⌋∗μ[di]
然后 ans=∏ni=1∏d|if[d]⌊ni⌋⌊mi⌋∗μ[di]
设s[i]=∏d|if[d]μ[di]
ans=∏ni=1s[i]⌊ni⌋⌊mi⌋
然后去处理一下g的前缀积,分块做一下就好了。
#include
#include
#include
#include
#include
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int maxn=1e6+7,mo=1e9+7;
ll i,j,k,l,t,n,m,ans,cas,r;
bool bz[maxn];
ll miu[maxn],p[maxn],sum[maxn],f[maxn],ji[maxn],g[maxn],chu[maxn][3];
ll qsm(ll x,ll y){
if(y<0)y+=mo-1;
ll z=1;
for(;y;y/=2,x=x*x%mo)if(y&1)z=z*x%mo;
return z;
}
int main(){
freopen("product.in","r",stdin);
freopen("product.out","w",stdout);
miu[1]=sum[1]=f[1]=ji[1]=ji[0]=g[0]=g[1]=1;chu[1][0]=chu[1][1]=chu[1][2]=1;
fo(i,2,maxn-7){
f[i]=(f[i-1]+f[i-2])%mo;ji[i]=1;
g[i]=1;
if(!bz[i])p[++p[0]]=i,miu[i]=-1;
fo(j,1,p[0]){
t=p[j]*i;if(t>maxn-7)break;
bz[t]=1;if(i%p[j]==0){break;}
miu[t]=-miu[i];
}
sum[i]=sum[i-1]+miu[i];
chu[i][0]=qsm(f[i],mo-2);chu[i][1]=1;chu[i][2]=f[i];
}
fo(i,1,maxn-7){
fo(j,1,(maxn-7)/i){
g[i*j]=g[i*j]*chu[i][miu[j]+1]%mo;
}
ji[i]=ji[i-1]*g[i]%mo;
}
for(scanf("%d",&cas);cas;cas--){
scanf("%d%d",&n,&m);
if(n>m)swap(n,m);ans=1;
l=1;
while(l<=n){
r=min(n/(n/l),m/(m/l));
t=0;
t=(n/l)*(m/l)%(mo-1);
ans=ans*qsm((ji[r]*qsm(ji[l-1],mo-2)%mo),t)%mo;
l=r+1;
}
printf("%lld\n",ans);
}
}