【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
原文地址:https://www.cnblogs.com/onioncyc/p/7944328.html