zoukankan      html  css  js  c++  java
  • 【CodeForces】585 E. Present for Vitalik the Philatelist

    【题目】E. Present for Vitalik the Philatelist

    【题意】给定n个数字,定义一种合法方案为选择一个数字Aa,选择另外一些数字Abi,令g=gcd(Ab1...Abx),要求满足g≠1且gcd(Aa,g)=1,求方案数取模1e9+7。2<=n<=5*10^5,2<=ai<=10^7。

    【算法】数论,计数问题

    【题解】

    考虑选择一些数字使得g≠1,容易想到枚举g值,O(n ln n)地枚举g的倍数,得到b[g]表示数列中数字为g的倍数的个数。

    那么含有公因数g的区间数为2^b[g]-1,考虑容斥。

    引入莫比乌斯函数μ(x),简单定义:μ(1)=1,含奇数个素因子μ(x)=-1,含偶数个素因子μ(x)=1,含重复素因子μ(x)=0。

    根据容斥原理的奇加偶减,应将-μ[g]作为系数,那么总方案数就是sum=Σ-μ(g)*(2^b[g]-1),g=2~max(ai)。

    接下来考虑区间和数字Aa组合,会减去gcd和Aa不互质的区间,也就是去掉公因数含有Aa的素因子的区间,这实际上也是莫比乌斯函数容斥。

    所以可以套用在原来的容斥上,也就是对于数字Aa,只要将Aa的所有因子g的μ(g)视为0,计算出来的sum就是数字Aa的贡献。

    那么再换个角度,含有公因数g的区间只会在数字Aa不含因子g的时候被贡献,这样的数字数实际上是n-b[g]。

    所以,ans=Σ-μ(g)*(2^b[g]-1)*(n-b[g]),g=2~max(ai)。

    最后,可以用自带容斥的方法避开μ的计算。最后视为对(2^b[g]-1)*(n-b[g])进行容斥(即使这样容斥没有实际含义),然后减去f[h](h=k*g),得到f[g]。ans=Σf[g]。(这种方法和埃式筛μ的本质相同)

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=500010,N=10000010,M=1e9+7;
    int n,x,b[N],fx[maxn],f[N],ans=0,mx=0;
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&x),mx=max(mx,x),b[x]++;
        fx[0]=1;for(int i=1;i<=n;i++)fx[i]=(fx[i-1]<<1)%M;
        for(int g=mx;g>=1;g--){
            x=b[g];
            for(int i=g+g;i<=mx;i+=g){
                x+=b[i];
                f[g]=(f[g]-f[i]+M)%M;
            }
            if(g!=1){
                f[g]=(f[g]+1ll*(fx[x]-1)*(n-x)%M)%M;
                ans=(ans+f[g])%M;
            }
        }
        printf("%d",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    linux命令---vi编辑器快速定位行数
    Linux如何查找大文件或目录总结
    Xargs用法详解(自创)
    linux如何模糊查找一个文件
    HashMap在什么场景下会由哪些内部方法导致线程不安全,至少给出一种场景
    索引失效(全面总结)
    异常处理(Exception Handling)
    JAVA异常及其异常处理方式
    Activity嵌套多个Fragment实现横竖屏切换
    iOS KVC(Key-Value Coding)
  • 原文地址:https://www.cnblogs.com/onioncyc/p/7944328.html
Copyright © 2011-2022 走看看