大意:
设f[i]为斐波那契数列的第i项,其中f[1]=1,f[2]=1。
给一个N*M的表格,[i,j]的数字为f[gcd(i,j)],求表格中的数积,对1e9+7取模。
分析:莫比乌斯反演题,和于神之怒有点像。
代码:
// luogu-judger-enable-o2
#include <iostream>
#include <cstdio>
#include <cmath>
#define LL long long
const LL mod=1000000007;
const LL maxn=1e6+7;
using namespace std;
LL T,n,m,cnt;
LL mul[maxn];
LL prime[maxn],not_prime[maxn];
LL fib[maxn],g[maxn],rev[maxn];
LL power(LL x,LL y)
{
if (y==0) return 1;
if (y==1) return x;
LL c=power(x,y/2);
c=(c*c)%mod;
if (y%2==1) c=(c*x)%mod;
return c;
}
void getmul(LL n)
{
mul[1]=1;
for (LL i=2;i<=n;i++)
{
if (!not_prime[i])
{
prime[++cnt]=i;
mul[i]=-1;
}
for (LL j=1;j<=cnt;j++)
{
if (i*prime[j]>n) break;
not_prime[i*prime[j]]=1;
if (i%prime[j]==0)
{
mul[i*prime[j]]=0;
break;
}
mul[i*prime[j]]=-mul[i];
}
}
fib[0]=0; fib[1]=1;
g[1]=1; rev[1]=1;
for (LL i=2;i<=n;i++)
{
g[i]=1;
fib[i]=(fib[i-1]+fib[i-2])%mod;
rev[i]=power(fib[i],mod-2);
}
for (LL i=1;i<=n;i++)
{
if (!mul[i]) continue;
LL x;
for (LL j=i;j<=n;j+=i)
{
if (mul[i]==1) x=fib[j/i];
else x=rev[j/i];
g[j]=(g[j]*x)%mod;
}
}
g[0]=1;
for (LL i=2;i<=n;i++) g[i]=(g[i]*g[i-1])%mod;
}
LL calc(LL n,LL m)
{
if (n>m) swap(n,m);
LL ans=1;
for (LL i=1,last;i<=n;i=last+1)
{
last=min(n/(n/i),m/(m/i));
ans=ans*(power(g[last]*power(g[i-1],mod-2)%mod,(n/i)*(m/i)%(mod-1)))%mod;
}
return ans;
}
int main()
{
scanf("%lld",&T);
getmul(maxn);
while (T--)
{
scanf("%lld%lld",&n,&m);
printf("%lld\n",calc(n,m));
}
}