zoukankan      html  css  js  c++  java
  • [BZOJ4305] 数列的GCD

    [BZOJ4305] 数列的GCD

    题目链接

    https://www.lydsy.com/JudgeOnline/problem.php?id=4305

    Solution

    (a_i)表示(d=i)时的答案,恰好(k)个不同也就是恰好(n-k)个相同,设(s=n-k)

    设有(c)个题目给出来数是的(i)的倍数,则可以得到(a_i)的表达式:

    [a_i=inom{c}{s}cdot (lfloorfrac{m}{i} floor-1)^{c-s}cdot lfloorfrac{m}{i} floor^{n-c}-sum_{j=2}^{m/i}a_{ij} ]

    我们发现前面的部分算到了(gcd)(i)的倍数的情况,所以在后面减掉。

    利用调和级数,复杂度为(O(nlog n))

    #include<bits/stdc++.h>
    using namespace std;
     
    void read(int &x) {
        x=0;int f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
      
    void print(int x) {
        if(x<0) putchar('-'),x=-x;
        if(!x) return ;print(x/10),putchar(x%10+48);
    }
    void write(int x) {if(!x) putchar('0');else print(x);putchar('
    ');}
     
    #define lf double
    #define ll long long 
     
    #define pii pair<int,int >
    #define vec vector<int >
     
    #define pb push_back
    #define mp make_pair
    #define fr first
    #define sc second
     
    #define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++) 
     
    const int maxn = 3e5+10;
    const int inf = 1e9;
    const lf eps = 1e-8;
    const int mod = 1e9+7;
     
    int a[maxn],t[maxn],n,m,k,b[maxn],fac[maxn],ifac[maxn],inv[maxn];
     
    int qpow(int a,int x) {
        int res=1;
        for(;x;x>>=1,a=1ll*a*a%mod) if(x&1) res=1ll*res*a%mod;
        return res;
    }
     
    void prepare(int l) {
        inv[0]=inv[1]=fac[0]=ifac[0]=1;
        FOR(i,1,l) fac[i]=1ll*fac[i-1]*i%mod;
        FOR(i,2,l) inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
        FOR(i,1,l) ifac[i]=1ll*ifac[i-1]*inv[i]%mod;
    }
     
    int c(int x,int y) {return 1ll*fac[x]*ifac[y]%mod*ifac[x-y]%mod;}
     
    int main() {
        read(n),read(m),read(k);for(int i=1,x;i<=n;i++) read(x),b[x]++;k=n-k;
        prepare(max(m,n));
        for(int i=1;i<=m;i++)
            for(int j=i;j<=m;j+=i) t[i]+=b[j];
        for(int i=m;i;i--) {
            if(t[i]<k) continue;
            a[i]=1ll*c(t[i],k)*qpow(m/i-1,t[i]-k)%mod*qpow(m/i,n-t[i])%mod;
            for(int j=i<<1;j<=m;j+=i) a[i]=(a[i]-a[j])%mod;
        }
        for(int i=1;i<=m;i++) printf("%d ",(a[i]+mod)%mod);puts("");
        return 0;
    }
    
  • 相关阅读:
    下拉选择框:数字从n到m
    event.target返回事件的目标节点(触发该事件的节点)
    nextSibling使用注意(html的注释)
    mysql导出 csv文件
    ie打印去掉页眉页脚
    jsp标签循环标签体
    String.format字符串格式化方法
    [**奇文共赏**补充问题] 据说看五遍能懂的人智商 > 200
    [转] ARP的处理办法!
    [转] 一张废手机卡的作用大全 (没试过)
  • 原文地址:https://www.cnblogs.com/hbyer/p/11061104.html
Copyright © 2011-2022 走看看