Codeforces803F Coprime Subsequences

来源:互联网 发布:windows exec函数 编辑:程序博客网 时间:2024/06/05 05:28

链接

  http://codeforces.com/problemset/problem/803/F

题目大意

  给你一个序列,问你有多少个子序列的gcd=1

题解

  这题直接入手的话应该就想到枚举gcd然后容斥,先加上所有子序列的个数2n1,然后减去gcd=2的,然后减去gcd=3的,然后减去gcd=5的,然后加上gcd=6的….以此类推
  你发现这个东西其实就是莫比乌斯函数,直接线性筛即可。
  问题是怎么快速统计含有某个数作为因子的数有多少个。
  显然可能计入答案的就是[1,max]这些约数,我们不可能每次枚举一个数然后去挨个取模。
  考虑一个数的约数的级别是O(N)的,因此可以O(NN)用一个桶预处理下。

代码

//容斥 #include <cstdio>#define maxn 100005#define ll long long#define mod 1000000007llusing namespace std;int mu[maxn], N, prime[maxn], mark[maxn], cnt[maxn], mi[maxn];void shai(){    int i, j;    mu[1]=1;    for(i=2;i<maxn;i++)    {        if(!mark[i]){prime[++*prime]=i;mu[i]=-1;}        for(j=1;i*prime[j]<maxn;j++)        {            mark[i*prime[j]]=1;            if(i%prime[j]==0)break;            mu[i*prime[j]]=-mu[i];        }    }}void init(){    int i, j, x;    scanf("%d",&N);    for(i=1;i<=N;i++)    {        scanf("%d",&x);        for(j=1;j*j<=x;j++)if(x%j==0)cnt[j]++, cnt[x/j]+=j!=x/j;    }    mi[0]=1;    for(i=1;i<maxn;i++)mi[i]=(mi[i-1]<<1)%mod;}int main(){    ll ans=0;    init();    shai();    for(int i=1;i<maxn;i++)ans=(ans+(mi[cnt[i]]-1)*mu[i])%mod;    printf("%I64d",(ans+mod)%mod);    return 0;}
0 0
原创粉丝点击