• bzoj4305 数列的GCD


    Description

    给出一个长度为N的数列{a[n]},1<=a[i]<=M(1<=i<=N)。 
    现在问题是,对于1到M的每个整数d,有多少个不同的数列b[1], b[2], ..., b[N],满足: 
    (1)1<=b[i]<=M(1<=i<=N); 
    (2)gcd(b[1], b[2], ..., b[N])=d; 
    (3)恰好有K个位置i使得a[i]<>b[i](1<=i<=N) 
    注:gcd(x1,x2,...,xn)为x1, x2, ..., xn的最大公约数。 
    输出答案对1,000,000,007取模的值。 

    Input

    第一行包含3个整数,N,M,K。 
    第二行包含N个整数:a[1], a[2], ..., a[N]。 

    Output

    输出M个整数到一行,第i个整数为当d=i时满足条件的不同数列{b[n]}的数目mod 1,000,000,007的值。 
     

    Sample Input

    3 3 3
    3 3 3

    Sample Output

    7 1 0

    Hint

    当d=1,{b[n]}可以为:(1, 1, 1), (1, 1, 2), (1, 2, 1), (1, 2, 2), (2, 1, 1), (2, 1, 2), (2, 2, 1)。 
    当d=2,{b[n]}可以为:(2, 2, 2)。 
    当d=3,因为{b[n]}必须要有k个数与{a[n]}不同,所以{b[n]}不能为(3, 3, 3),满足条件的一个都没有。 
    对于100%的数据,1<=N,M<=300000, 1<=K<=N, 1<=a[i]<=M。 
     
     
    组合数学
    详见题解:CSDN->  /geotcbrl/article/details/49622731
     
    分为2类:
    原数的约数不含 i :必须修改成 i 的倍数(共 m/i 个)。
    原数的约数已经含 i :一部分不修改,一部分强制修改(共 m/i-1个)
    最后把gcd是 i 的倍数的情况筛掉即可。
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const int mod=1000000007;
    int n,m,k,t[300003];
    ll fac[300003],inv[300003],f[300003];
    inline ll Pow(ll x,int y){
        ll res=1;
        for(;y;y>>=1){
            if(y&1) res=res*x%mod;
            x=x*x%mod;
        }return res;
    }
    inline ll C(int N,int M) {return fac[N]*inv[M]%mod*inv[N-M]%mod;}
    int main(){
        scanf("%d%d%d",&n,&m,&k); int q;
        fac[0]=inv[0]=1;
        for(int i=1;i<=n;++i){
            scanf("%d",&q),++t[q]; //开个桶存起来
            fac[i]=fac[i-1]*i%mod;
            inv[i]=inv[i-1]*Pow((ll)i,mod-2)%mod; //预处理出阶乘以及其逆元
        }
        for(int i=1;i<=m;++i){
            int cnt=0;
            for(int j=i;j<=m;j+=i) cnt+=t[j]; //统计i的倍数的个数
            if(cnt<n-k) continue;
            f[i]=C(cnt,n-k)*Pow((ll)(m/i-1),cnt-n+k)%mod*Pow((ll)(m/i),n-cnt)%mod;
        //f[i]=对i的倍数强制修改的方案*其他非i倍数的修改方案数 }
    for(int i=m;i;--i) //逆序筛去gcd为i的倍数的情况 for(int j=i*2;j<=m;j+=i) f[i]=(f[i]-f[j]+mod)%mod; for(int i=1;i<=m;++i) printf("%lld ",f[i]); return 0; }
  • 相关阅读:
    Fluentd部署:如何监控Fluentd
    【615】国内国外经纬度坐标转换
    【614】矢量数据转栅格数据(cv2.fillPoly/cv2.polylines)
    【613】U-Net 相关
    【612】深度学习模型相关问题
    【611】keras 后端 backend 相关函数(Dice实现)
    面试官:new 关键字在 JVM 中是如何执行的?
    IntelliJ IDEA 2021.2 发布,这次要干掉 FindBugs 了!!
    Nginx 实现 10w+ 并发之 Linux 内核优化
    我们真的需要全栈开发吗?
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/9709390.html
Copyright © 2020-2023  润新知