CodeForces 585E

来源:互联网 发布:sql商务系统开发培训 编辑:程序博客网 时间:2024/06/01 20:04

ff[i]:i的倍数的个数
gg[i]:gcd==i的集合的个数
kk[i]:和i不互质的数的个数

#include<cstdio>#include<cstring>#include<iostream>using namespace std;const int mod=1e9+7;typedef __int64 LL;int _pow(int a,int b){    int c=1;    while(b){        if(b&1){            c=(LL)c*a%mod;        }        a=(LL)a*a%mod;        b/=2;    }    return c;}const int N=1e7+10;int ff[N],gg[N],kk[N],mu[N],pn,pri[N];void init(){    memset(ff,0,sizeof(ff));    pn=0;    int n=1e7;    for(int i=2;i<=n;i++){        if(!ff[i]){            mu[i]=1;            pri[pn++]=i;        }        for(int j=0;j<pn;j++){            if(pri[j]>n/i)break;            ff[i*pri[j]]=1;            if(i%pri[j]==0){                mu[i*pri[j]]=0;                break;            }            else {                mu[i*pri[j]]=-mu[i];            }        }    }}void prin(int mx){    for(int i=2;i<=mx;i++){        printf("%d:%d %d %d\n",i,ff[i],gg[i],kk[i]);    }}int main(){    #ifdef DouBi    freopen("in.cpp","r",stdin);    //freopen("out.cpp","w",stdout);    #endif // DouBi    int n;    init();//    for(int i=2;i<=10;i++){//        printf("%d %d\n",i,mu[i]);//    }    while(scanf("%d",&n)!=EOF){        memset(ff,0,sizeof(ff));        memset(gg,0,sizeof(gg));        memset(kk,0,sizeof(kk));        int mx=2;        for(int i=0;i<n;i++){            int a;scanf("%d",&a);            mx=max(mx,a);            ff[a]++;        }        for(int i=2;i<=mx;i++){            for(int j=i*2;j<=mx;j+=i){                ff[i]+=ff[j];            }        }        for(int i=2;i<=mx;i++)if(mu[i]){            for(int j=i;j<=mx;j+=i){                kk[j]+=mu[i]*ff[i];                if(kk[j]>=mod)kk[j]-=mod;                if(kk[j]<0)kk[j]+=mod;            }        }        for(int i=mx;i>=2;i--){            gg[i]=_pow(2,ff[i])-1;            if(gg[i]<0)gg[i]+=mod;            for(int j=i*2;j<=mx;j+=i){                gg[i]-=gg[j];                if(gg[i]<0)gg[i]+=mod;            }        }        //prin(mx);        int ans=0;        for(int i=2;i<=mx;i++){            ans+=(LL)(n-kk[i])*gg[i]%mod;            if(ans>=mod)ans-=mod;        }        printf("%d\n",ans);    }    return 0;}
0 0