zoukankan      html  css  js  c++  java
  • 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
    ",ans);
        }    
        
        return 0;
    }

  • 相关阅读:
    C++指针详解
    C++中#include包含头文件带 .h 和不带 .h 的区别
    #if的使用说明
    非常简单的语音朗读功能
    C#基础笔记(第十一天)
    C#基础笔记(第十天)
    手机管理系统
    编程书籍大集合
    centos 安装多实例数据库
    Python3 网络爬虫(请求库的安装)
  • 原文地址:https://www.cnblogs.com/Heey/p/9100705.html
Copyright © 2011-2022 走看看