zoukankan      html  css  js  c++  java
  • 洛谷P3704 [SDOI2017]数字表格

    题目描述

    Doris刚刚学习了fibonacci数列。用f[i]f[i] 表示数列的第ii 项,那么

    f[0]=0f[0]=0 ,f[1]=1f[1]=1 ,

    f[n]=f[n-1]+f[n-2],ngeq 2f[n]=f[n1]+f[n2],n2

    Doris用老师的超级计算机生成了一个n×mn×m 的表格,

    ii 行第jj 列的格子中的数是f[gcd(i,j)]f[gcd(i,j)] ,其中gcd(i,j)gcd(i,j) 表示i,ji,j 的最大公约数。

    Doris的表格中共有n×mn×m 个数,她想知道这些数的乘积是多少。

    答案对10^9+7109+7 取模。

    输入输出格式

    输入格式:

    有多组测试数据。

    第一个一个数TT ,表示数据组数。

    接下来TT 行,每行两个数n,mn,m

    输出格式:

    输出TT 行,第ii 行的数是第ii 组数据的结果

    输入输出样例

    输入样例#1: 复制
    3
    2 3
    4 5
    6 7
    输出样例#1: 复制
    1
    6
    960

    说明

    10\%10% 的数据,1leq n,mleq 1001n,m100

    30\%30% 的数据,1leq n,mleq 10001n,m1000

    另外存在30\%30% 的数据,Tleq 3T3

    100\%100% 的数据,Tleq1000,1leq n,mleq 10^6T1000,1n,m106

    时间限制:5s

    内存限制:128MB

    一道明年也做不出来的反演题,。

    参考了一下洛谷题解

    $$prod_{d=1}^nprod_{i=1}^nprod_{j=1}^mif(gcd(i,j)==d)f[gcd(i,j)]$$

    $$prod_{d=1}^{n}f[d]^{sum_{i=1}^{n/d}sum_{j=1}^{m/d}[gcd(i,j)==1]}$$

    观察上面的$$sum_{i=1}^{n/d}sum_{j=1}^{m/d}[gcd(i,j)==1]$$

    这是一个经典反演问题,它等价于

    $$sum_{i=1}^{n/d}mu(i)[frac{n}{id}][frac{m}{id}]$$

    令$T=id$

    $$prod_{T=1}^{n}prod_{d|T}f[d]^{[n/T][m/T]mu(T/d)}$$

    $$prod_{T=1}^{n}(prod_{d|T}f[d]^{mu(T/d)})^{[n/T][m/T]}$$

    然后对于$[n/T]$和$[m/T]$分块

    里面的那一个直接暴力,

    不明白为什么最后要%mod-1QWQ...

    // luogu-judger-enable-o2
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int mod=1e9+7;
    const int MAXN=1e6;
    inline int read()
    {
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    int fastpow(int a,int p)
    {
        int base=1;
        while(p)
        {
            if(p&1) base=1LL*base%mod*a%mod;
            a=1LL*a%mod*a%mod%mod;
            p>>=1;
        }
        return base%mod;
    }
    int mu[MAXN+10],sum[MAXN+10],fib[MAXN+10],nfib[MAXN+10],vis[MAXN+10],prime[MAXN],tot;
    void Pre()
    {
        fib[1]=1;
        for(int i=2;i<=MAXN;i++) fib[i]=(fib[i-1]%mod+fib[i-2]%mod)%mod;
        for(int i=1;i<=MAXN;i++) 
            nfib[i]=(fastpow(fib[i],mod-2)+mod)%mod;
        vis[1]=1;mu[1]=1;
        for(int i=2;i<=MAXN;i++)
        {
            if(!vis[i]) prime[++tot]=i,mu[i]=-1;
            for(int j=1;j<=tot&&i*prime[j]<=MAXN;j++)
            {
                vis[i*prime[j]]=1;
                if(i%prime[j]==0) {mu[i*prime[j]]=0;break;}
                else mu[i*prime[j]]=-mu[i];
            }
        }
        fill(sum,sum+MAXN,1);
        for(int i=1;i<=MAXN;i++)
        {
            if(mu[i]==0) continue;
            for(int j=i;j<=MAXN;j+=i)
            {
                if(mu[i]==-1) sum[j]=1ll*sum[j]%mod*nfib[j/i]%mod;
                if(mu[i]==1)  sum[j]=1ll*sum[j]%mod*fib[j/i]%mod;
            }
        }
        for(int i=1;i<=MAXN;i++) sum[i]=1ll*sum[i-1]*sum[i]%mod;
    }
    int main()
    {
        #ifdef WIN32
        freopen("a.in","r",stdin);
        #endif
        Pre();    
        int QWQ=read();
        while(QWQ--)
        {
            int N=read(),M=read();
            if(N>M) swap(N,M);
            long long int ans=1;
            for(int i=1,nxt;i<=N;i=nxt+1)
            {
                nxt=min(N/(N/i),M/(M/i));
                long long int pw=1ll*sum[nxt]*fastpow(sum[i-1],mod-2)%mod;
                ans=(1ll*ans*(fastpow(pw,1ll*(N/i)*(M/i)%(mod-1))))%mod;
            }
            printf("%lld
    ",(ans+mod)%mod);
        }
        return 0;
    }
  • 相关阅读:
    深入浅出SQL Server 2008 分区函数和分区表
    数据库的恢复模式
    Windows Server 2003网络负载均衡的实现(转)
    SharePoint2010网站备份还原简单介绍
    HTTP协议详解(转)
    SharePoint 2010之LINQ与SPMetal
    moss 自定义文档库文档图标
    SharePoint 2010环境搭建
    C#中的yield关键字
    .NET开发中你可能会用到的常用方法总结(添加ing...)
  • 原文地址:https://www.cnblogs.com/zwfymqz/p/8592328.html
Copyright © 2011-2022 走看看