数学 gcd

来源:互联网 发布:北京新华电脑学校java 编辑:程序博客网 时间:2024/05/22 07:05

题面请去内网找

这题的正解用到了容斥原理,只要统计出(用一个桶)有某个数作为因数的数的个数。sum[i]表示有多少数有一个因数是i.
很明显这样就可以利用容斥原理了。而容斥系数就是莫比乌斯函数,线性筛即可。ans只要在原有基础上+=μ[i]*sum[i]。

#pragma GCC optimize("O3")#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<cmath>#include<algorithm>#define N 200005#define ll long longusing namespace std;int read(){    int sum=0,f=1;char x=getchar();    while(x<'0'||x>'9'){if(x=='-')f=-1;x=getchar();}    while(x>='0'&&x<='9'){sum=(sum<<1)+(sum<<3)+x-'0';x=getchar();}    return sum*f;}int n,m,maxx,tot,w[500005],sum[500005],a[N];int v[500005],mark[500005],pri[500005];void init(){    w[1]=1;    for(int i=2;i<=maxx;i++)    {        if(!mark[i])        {            pri[++tot]=i;            w[i]=-1;        }        for(int j=1;j<=tot;j++)        {            if(pri[j]*i>maxx)break;            mark[pri[j]*i]=1;            if(i%pri[j]==0)            {                w[pri[j]*i]=0;                break;            }            w[pri[j]*i]=-w[i];        }    }}int main(){    n=read();m=read();    for(int i=1;i<=n;i++)a[i]=read(),maxx=max(maxx,a[i]);    init();    int x;ll ans=0;    while(m--)    {        x=read();        if(v[x]==0)        {            int h=sqrt(a[x]);v[x]=1;            for(int i=1;i<=h;i++)                if(!(a[x]%i))                {                    ans+=sum[i]*w[i];sum[i]++;                    if(i*i!=a[x]){ans+=sum[a[x]/i]*w[a[x]/i];sum[a[x]/i]++;}                }        }        else        {            int h=sqrt(a[x]);v[x]=0;            for(int i=1;i<=h;i++)                if(!(a[x]%i))                {                    sum[i]--;ans-=sum[i]*w[i];                    if(i*i!=a[x]){sum[a[x]/i]--;ans-=sum[a[x]/i]*w[a[x]/i];}                }        }        printf("%lld\n",ans);    }}
原创粉丝点击