codeforces803F Coprime Subsequences -- 莫比乌斯函数+容斥

来源:互联网 发布:淘宝客户管理 编辑:程序博客网 时间:2024/06/13 08:17

题目大意:

给定一个序列,求有多少个子序列的gcd等于1。

首先想到枚举每个数作为gcd,统计次数,再容斥一下。
统计答案时当这个数有偶数个约数时系数是-1,奇数个约数时是1。
然后我们发现这就是个莫比乌斯函数。
用线性筛求出莫比乌斯函数就可以了。

代码:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;#define M 1000000007#define N 100010int x,i,j,k,n,m,f[N],S,Ma,Ans,mu[N],p[N],Cnt;bool b[N];inline int Max(int x,int y){return x<y?y:x;}inline int Pow(int x,int y){    if(y==0)return 1;    int Ans=Pow(x,y>>1);    Ans=1ll*Ans*Ans%M;    if(y&1)return 1ll*Ans*x%M;    return Ans;}inline void Init(){    mu[1]=1;    for(i=2;i<=Ma;i++){        if(!b[i])p[++Cnt]=i,mu[i]=-1;        for(j=1;j<=Cnt&&p[j]*i<=Ma;j++){            b[p[j]*i]=1;            if(!(i%p[j]))break;            mu[p[j]*i]=-mu[i];        }    }}int main(){    scanf("%d",&n);    for(i=1;i<=n;i++){        scanf("%d",&x);Ma=Max(Ma,x);        S=sqrt(x);        for(j=1;j<=S;j++)        if(x%j==0){            f[j]++;            if(j*j<x)f[x/j]++;        }    }    Init();    for(i=1;i<=Ma;i++)Ans=(Ans+(Pow(2,f[i])-1)*mu[i])%M;    printf("%d\n",(Ans+M)%M);    return 0;}
阅读全文
0 0
原创粉丝点击