BZOJ 4816 数字表格

Posted on 2017-04-15 23:54  ziliuziliu  阅读(119)  评论(0编辑  收藏  举报

要是我生在SD多好啊。这题多良心啊。

(为什么我还在写题呢)

(我还得考一场NOIP233)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 1000050
#define mod 1000000007
using namespace std;
long long t,n,m,miu[maxn],f1[maxn],f2[maxn],g1[maxn],g2[maxn],ans,prime[maxn],tot=0;
bool vis[maxn];
long long f_pow(long long a,long long b)
{
    long long ans=1,base=a;
    while (b)
    {
        if (b&1) ans=(ans*base)%mod;
        base=(base*base)%mod;
        b>>=1;
    }
    return ans;
}
void get_table()
{
    miu[1]=1;
    for (long long i=2;i<=maxn-50;i++)
    {
        if (!vis[i])
        {
            vis[i]=true;miu[i]=-1;
            prime[++tot]=i;
        }
        for (long long j=1;j<=tot && i*prime[j]<=maxn-50;j++)
        {
             vis[i*prime[j]]=true;
             if (i%prime[j]) {miu[i*prime[j]]=-miu[i];continue;}
             else {miu[i*prime[j]]=0;break;}
        }
    }
    f1[1]=f2[1]=g1[1]=g2[1]=1;g2[0]=1;
    for (long long i=2;i<=maxn-50;i++) {g1[i]=1;f1[i]=(f1[i-1]+f1[i-2])%mod;f2[i]=f_pow(f1[i],mod-2);}
    for (long long i=2;i<=maxn-50;i++)
        for (long long j=1;j*i<=maxn-50;j++)
        {
            if (miu[j]==-1) g1[i*j]=(g1[i*j]*f2[i])%mod;
            else if (miu[j]==1) g1[i*j]=(g1[i*j]*f1[i])%mod;
        }
    for (long long i=2;i<=maxn-50;i++) {g1[i]=(g1[i]*g1[i-1])%mod;g2[i]=f_pow(g1[i],mod-2);}
}
int main()
{
    scanf("%lld",&t);get_table();
    for (long long i=1;i<=t;i++)
    {
        scanf("%lld%lld",&n,&m);
        ans=1;long long l=1,r=0;
        if (n>m) swap(n,m);
        while (l<=n)
        {
            r=min(n/(n/l),m/(m/l));
            ans=(ans*f_pow(g1[r]*g2[l-1]%mod,(n/l)*(m/l)%(mod-1)))%mod;
            l=r+1;
        }
        printf("%lld\n",ans);
    }
    return 0;
}