• [bzoj4816] [Sdoi2017]数字表格


    来自FallDream的博客,未经允许,请勿转载,谢谢。


    题意:T组数据,求$prod_{i=1}^{n}prod_{j=1}^{m}f[gcd(i,j)]$,其中$f[i]$是斐波那契数列的第i项。T<=1000 n,m<=10^6

    题解:让n<=m,考虑枚举斐波那契数列每一项被计算了多少次,列出式子

    $$Ans=prod_{k=1}^{n}f[k]^{sum_{i=1}^{lfloorfrac{n}{k} floor}sum_{m=1}^{lfloorfrac{n}{k} floor}sum_{d|i,d|j}mu(d)}$$

    老套路,把miu拆出来

    $$Ans=prod_{k=1}^{n}f[k]^{sum_{d=1}^{lfloorfrac{n}{k} floor}mu(d)lfloorfrac{n}{kd} floorlfloorfrac{m}{kd} floor}$$

    令$T=kd$,得到

    $$Ans=prod_{T=1}^{n}prod_{d|T}{f[d]}^{{mu(frac{T}{d})}^{lfloor frac{n}{T} floor lfloor frac{m}{T} floor}}$$

    发现$prod_{d|T}{f[d]^{mu(frac{T}{d})}}$可以预处理然后前缀积,而$lfloorfrac{n}{T} floor$和$lfloorfrac{m}{T} floor$只有根号种取值,所以这道题就做完了

    复杂度$O(Tsqrt{n}logn)$

    #include<cstdio>
    #include<iostream>
    #define ll long long
    #define MN 1000000
    #define mod 1000000007
    using namespace std;
    inline int read()
    {
        int x=0;char ch=getchar();
        while(ch<'0'||ch>'9')ch=getchar();
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x;
    }
    
    int mu[MN+5],f[MN+5],g[MN+5],s[MN],num=0,n,m,ans,inv[MN+5];
    bool b[MN+5];
    
    int pow(int x,int k)
    {
        if(k==-1) return inv[x];
        int sum=1;
        for(;k;k>>=1,x=1LL*x*x%mod)
            if(k&1) sum=1LL*sum*x%mod;
        return sum; 
    }
    
    int main()
    {    
        mu[1]=f[1]=g[1]=g[0]=1;
        for(int i=2;i<=MN;i++)f[i]=(f[i-1]+f[i-2])%mod,g[i]=1;
        for(int i=2;i<=MN;i++)
        {
            if(!b[i]) s[++num]=i,mu[i]=-1;
            for(int j=1;s[j]*i<=MN;j++)
            {
                b[s[j]*i]=1;
                if(i%s[j]==0) break;
                else mu[s[j]*i]=-mu[i];
            }
        }
    
        for(int i=1;i<=MN;i++) inv[i]=pow(f[i],mod-2);    
        for(int i=1;i<=MN;i++)
            for(int j=i;j<=MN;j+=i)
                g[j]=1LL*g[j]*(mu[j/i]==-1?inv[i]:pow(f[i],mu[j/i]))%mod;
        for(int i=2;i<=MN;i++) g[i]=1LL*g[i]*g[i-1]%mod;
        for(int T=read();T;T--)
        {
            n=read();m=read();ans=1;
            if(n>m)swap(n,m);
            for(int i=1,last;i<=n;i=last+1)
            {
                last=min(n/(n/i),m/(m/i));
    ans=1LL*ans*pow(1LL*g[last]*pow(g[i-1],mod-2)%mod,1LL*(n/i)*(m/i)%(mod-1))%mod; } printf("%d ",ans); } return 0; }
  • 相关阅读:
    C# 创建与读写配置文件
    C# 绘图三种方式
    WindowsForms获取服务名称
    Hbase之JAVA API不能远程访问问题解决
    Jenkins之自动构建
    Jenkins配置匿名用户拥有只读权限
    XShell中文乱码问题解决
    mybatis之关联(2)
    mybatis之动态SQL
    mybatis之一对一关联
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj4816.html
Copyright © 2020-2023  润新知