zoukankan      html  css  js  c++  java
  • BZOJ4816: [Sdoi2017]数字表格

    【传送门:BZOJ4816


    简要题意:

      设f[i]为斐波那契数列的第i项(f[0]=0,f[1]=1)

      有一个n*m的表格,第i行第j列的格子上的数为f[gcd(i,j)],求出n*m的所有格子的乘积


    题解:

      莫比乌斯反演

      实际上就是求$prod_{i=1}^{n}prod_{j=1}^{m}f[gcd(i,j)]$

      按照套路先枚举d=gcd(i,j),然后根据反演公式得到$$prod_{d=1}^{n}f[d]^{sum_{i=1}^{frac{n}{d}}mu(i)*frac{n}{d*i}*frac{m}{d*i}}$$

      还不能直接做,时间复杂度有点高,我们设x=di,设$g(d)=prod_{d|x}f[d]^{mu(frac{x}{d})}$,得到原式等于$prod_{x=1}^{n}g(x)^{frac{n}{x}*frac{m}{x}}$

      求g(d)就用更新倍数的方法求,然后直接整除分块就行了

      PS:BZOJ毒瘤卡常,求逆元时需要O(n)求逆元


    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    typedef long long LL;
    LL Mod=1e9+7;
    LL p_mod(LL a,LL b)
    {
        LL ans=1;
        while(b!=0)
        {
            if(b%2==1) ans=ans*a%Mod;
            a=a*a%Mod;b/=2;
        }
        return ans;
    }
    int miu[1100000],prime[1100000],v[1100000];
    LL f[1100000],nyf[1100000],nyg[1100000],sg[1100000];
    LL sf[1100000],g[1100000];
    void pre(int n)
    {
        miu[1]=1;int m=0;
        for(int i=2;i<=n;i++)
        {
            if(v[i]==0)
            {
                v[i]=i;
                prime[++m]=i;
                miu[i]=-1;
            }
            for(int j=1;j<=m;j++)
            {
                if(prime[j]>n/i||prime[j]>v[i]) break;
                v[i*prime[j]]=prime[j];
                if(i%prime[j]==0) miu[i*prime[j]]=0;
                else miu[i*prime[j]]=-miu[i];
            }
        }
        f[0]=0;f[1]=1;
        for(int i=2;i<=n;i++) f[i]=(f[i-1]+f[i-2])%Mod;
        sf[0]=1;
        for(int i=1;i<=n;i++) sf[i]=sf[i-1]*f[i]%Mod;
        nyf[0]=nyf[1]=1;
        LL d=p_mod(sf[n],Mod-2);
        for(int i=n;i>=1;i--) nyf[i]=d*sf[i-1]%Mod,d=d*f[i]%Mod;
        for(int i=1;i<=n;i++) g[i]=1;
        for(int i=2;i<=n;i++)
        {
            for(int j=1;i*j<=n;j++)
            {
                LL d;
                if(miu[j]==1) d=f[i];
                else if(miu[j]==0) d=1;
                else d=nyf[i];
                g[i*j]=g[i*j]*d%Mod;
            }
        }
        sg[0]=1;
        for(int i=1;i<=n;i++) sg[i]=sg[i-1]*g[i]%Mod;
        nyg[n]=p_mod(sg[n],Mod-2);
        for(int i=n;i>=1;i--) nyg[i-1]=nyg[i]*g[i]%Mod;
    }
    int main()
    {
        pre(1000000);
        int T,n,m;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&n,&m);
            if(n>m) swap(n,m);
            LL ans=1;
            for(int i=1,j;i<=n;i=j+1)
            {
                j=min(n/(n/i),m/(m/i));
                ans=ans*p_mod(sg[j]*nyg[i-1]%Mod,LL(n/i)*(m/i)%(Mod-1))%Mod;
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }

     

  • 相关阅读:
    浅谈css中的盒模型(框模型)
    Linux 字符设备驱动及一些简单的Linux知识
    java实现person类 override(重写) comparable接口
    java之内部类
    mac下sublime text3 安装px转rem插件
    python pip安装扩展报错
    curl http_code 状态码
    sed 批量替换文件
    centos 7 开机优化shell
    一个tcp连接可以发多少http请求
  • 原文地址:https://www.cnblogs.com/Never-mind/p/9854263.html
Copyright © 2011-2022 走看看