BZOJ#4816. [Sdoi2017]数字表格

4816: [Sdoi2017]数字表格

Time Limit: 50 Sec  Memory Limit: 128 MB
Submit: 1302  Solved: 652

Description

Doris刚刚学习了fibonacci数列。用f[i]表示数列的第i项,那么
f[0]=0
f[1]=1
f[n]=f[n-1]+f[n-2],n>=2
Doris用老师的超级计算机生成了一个n×m的表格,第i行第j列的格子中的数是f[gcd(i,j)],其中gcd(i,j)表示i,
j的最大公约数。Doris的表格中共有n×m个数,她想知道这些数的乘积是多少。答案对10^9+7取模。

Input

有多组测试数据。

第一个一个数T,表示数据组数。
接下来T行,每行两个数n,m
T<=1000,1<=n,m<=10^6

Output

输出T行,第i行的数是第i组数据的结果

Sample Input

3
2 3
4 5
6 7

Sample Output

1
6
960
 

Problem:    
              

                         

Solution:
推导:        
                  
套路枚举gcd:
                 

                                                                  

根据公式二:    
                
枚举dx:
                   
                      
暴力预处理出:  
                  
void getmu()
{
    mu[1]=1;
    for(int i=2;i<N;i++)
    {
        if(!vis[i]) prime[++cnt]=i,mu[i]=-1;
        for(int j=1;j<=cnt;j++)
        {
            if(i*prime[j]>=N) break;
            vis[i*prime[j]]=1;
            if(i%prime[j]==0) {mu[i*prime[j]]=0;break;}
            else mu[i*prime[j]]=-mu[i];
        }
    }
    f[1]=1;
    for(int i=2;i<N;i++) f[i]=(f[i-1]+f[i-2])%mod;
    for(int i=1;i<N;i++) inver[i]=qpow(mod-2,f[i]);
    fill(g,g+N,1);
    for(int i=1;i<N;i++)
        for(int j=1;i*j<N;j++)
        if(mu[j]) g[i*j]=g[i*j]*(mu[j]==1?f[i]:inver[i])%mod;
    for(int i=1;i<N;i++) g[i]=g[i]*g[i-1]%mod;
}

 


 

附上代码: 
 
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+12;
const int mod=1e9+7;
int vis[N],mu[N],prime[N],cnt;
long long f[N],g[N],inver[N];

long long qpow(long long a,long long b)
{
    long long ans=1LL;
    while(a)
    {
        if(a&1) ans=ans*b%mod;
        b=b*b%mod;
        a>>=1;    
    }
    return ans;
}
void getmu()
{
    mu[1]=1;
    for(int i=2;i<N;i++) 
    {
        if(!vis[i]) prime[++cnt]=i,mu[i]=-1;
        for(int j=1;j<=cnt;j++) 
        {
            if(i*prime[j]>=N) break;
            vis[i*prime[j]]=1;
            if(i%prime[j]==0) {mu[i*prime[j]]=0;break;}
            else mu[i*prime[j]]=-mu[i];
        }
    }
    f[1]=1;
    for(int i=2;i<N;i++) f[i]=(f[i-1]+f[i-2])%mod;
    for(int i=1;i<N;i++) inver[i]=qpow(mod-2,f[i]);
    fill(g,g+N,1);
    for(int i=1;i<N;i++)
        for(int j=1;i*j<N;j++) 
        if(mu[j]) g[i*j]=g[i*j]*(mu[j]==1?f[i]:inver[i])%mod;
    for(int i=1;i<N;i++) g[i]=g[i]*g[i-1]%mod;
}


int main()
{
    freopen("a.in","r",stdin);
    getmu();
    int T;scanf("%d",&T);
    while(T--) 
    {
        int n,m;scanf("%d%d",&n,&m);
        if(n>m) swap(n,m);
        long long ans=1;
        int pos;
        for(int i=1;i<=n;i=pos+1)
        {
            pos=min(n/(n/i),m/(m/i));
            ans=ans*qpow((long long)(n/i)*(m/i),g[pos]*qpow(mod-2,g[i-1])%mod)%mod;
        }
        printf("%lld\n",ans);
    }    
    
    return 0;
}

 


 

posted @ 2018-05-28 16:14  Heey  阅读(221)  评论(0编辑  收藏  举报