• bzoj 4816: [Sdoi2017]数字表格


    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取模。

    解题报告:
    这题和之前的差不多.设(g[x])(gcd==x)的数对个数,然后就是基本的反演了
    (sum_{d=1}^nf[d]^{g[d]})
    (g[d]=sum_{i|d}lfloor m/d floorlfloor n/d floormu(d/i))
    这个明显可以数论分块,所以我们处理一下(g[d]^mu)的前缀积,对于除法再求个逆即可

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #define RG register
    #define il inline
    #define iter iterator
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define Min(a,b) ((a)<(b)?(a):(b))
    using namespace std;
    typedef long long ll;
    const int N=1e6+5,mod=1e9+7;
    int q[1005][2],lim,prime[N],num=0,pi[N];bool vis[N];
    void solve(){
        pi[1]=1;int to;
        for(int i=2;i<=lim;i++){
            if(!vis[i]){
                prime[++num]=i;
                pi[i]=-1;
            }
            for(int j=1;j<=num && i*prime[j]<=lim;j++){
                to=i*prime[j];vis[to]=true;
                if(i%prime[j])pi[to]=-pi[i];
                else{
                    pi[to]=0;
                    break;
                }
            }
        }
    }
    ll f[N],sum[N];
    ll qm(ll x,ll k){
        ll sum=1;
        while(k){
            if(k&1)sum*=x,sum%=mod;
            x*=x;x%=mod;k>>=1;
        }
        return sum;
    }
    ll query(int n,int m){
        int j;ll ret=1;
        for(int i=1;i<=n;i=j+1){
            j=min(n/(n/i),m/(m/i));
            ret=ret*qm(sum[j]*qm(sum[i-1],mod-2)%mod,(ll)(n/i)*(m/i))%mod;
        }
        return ret;
    }
    ll ni[N],g[N];
    void work()
    {
        int Q;cin>>Q;
        for(int i=1;i<=Q;i++){
            scanf("%d%d",&q[i][0],&q[i][1]);
            if(q[i][0]>q[i][1])swap(q[i][0],q[i][1]);
            lim=Max(lim,q[i][0]);
        }
        solve();
        f[0]=0;f[1]=1;
        for(int i=2;i<=lim;i++){
            f[i]=f[i-1]+f[i-2];
            if(f[i]>=mod)f[i]-=mod;
        }
        for(int i=0;i<=lim;i++)ni[i]=qm(f[i],mod-2);
        for(int i=1;i<=lim;i++)g[i]=1;
        for(int i=1;i<=lim;i++)
            for(int j=i;j<=lim;j+=i)
                if(pi[j/i]==1)g[j]=g[j]*f[i]%mod;
                else if(pi[j/i]==-1)g[j]=g[j]*ni[i]%mod;
        sum[0]=1;
        for(int i=1;i<=lim;i++){
            sum[i]=sum[i-1]*g[i]%mod;
        }
        for(int i=1;i<=Q;i++){
            printf("%lld
    ",query(q[i][0],q[i][1]));
        }
    }
    
    int main()
    {
        work();
        return 0;
    }
    
  • 相关阅读:
    怎么使用git来管理项目版本?
    《我的四季》 张浩
    [代码片段]读取BMP文件(二)
    [代码片段]读取BMP文件
    《构建之法》阅读笔记02
    二维数组
    学习进度二
    《构建之法》阅读笔记01
    数组
    软件工程第一周开课博客
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7513182.html
Copyright © 2020-2023  润新知