codeforces548E Mike and Foam -- 容斥

来源:互联网 发布:独立网络经纪人登录 编辑:程序博客网 时间:2024/05/22 13:18

先对所有数质因数分解。显然相同的质因数可以看成一个。这样一个数最多只有 6 个质因数。
维护 si 表示 i 当前是多少个数的因数。加入数 x 时枚举它的所有因数,容斥一下就可以了。
时间复杂度O(26×q)

代码

#include<cmath>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;#define N 200010#define M 500010#define ll long longinline char nc(){    static char buf[100000],*p1=buf,*p2=buf;    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}inline void Read(int& x){    char c=nc();    for(;c<'0'||c>'9';c=nc());    for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());}char ss[30];int Len;inline void Print(ll x){    if(!x)putchar(48);    for(Len=0;x;x/=10)ss[++Len]=x%10;    while(Len)putchar(ss[Len--]+'0');    putchar('\n');}ll Ans;int s,a[N],c[N][20],l[N],p[N],i,j,k,n,m,f[M],num,Res,q,t;int x,y;bool b[M];inline void Init(){    for(i=2;i<=m;i++){        if(!b[i])p[++num]=i;        int t;        for(j=1;j<=num&&(t=p[j]*i)<=m;j++){            b[t]=1;            if(!(i%p[j]))break;        }    }}inline void Dfs(int x,int y,int s,bool b){    if(x==l[y]+1){        Res+=(b?1:-1)*f[s];        return;    }    Dfs(x+1,y,s,b);    Dfs(x+1,y,s*c[y][x],b^1);}inline void Dfs2(int x,int y,int s,int d){    if(x==l[y]+1){        if(s>1)f[s]+=d;        return;    }    Dfs2(x+1,y,s,d);    Dfs2(x+1,y,s*c[y][x],d);}inline void Update(int x,int d){    if(a[x]==1){        Ans+=d*(k+t);t+=d;        if(d==-1)Ans++;        return;    }    Res=0;    Dfs(1,x,1,0);    Ans+=t*d;    Ans+=(k-Res)*d;    Dfs2(1,x,1,d);    k+=d;}int main(){    Read(n);Read(q);m=2;    for(i=1;i<=n;i++)Read(a[i]),m=max(m,a[i]);    Init();    for(i=1;i<=n;i++){        x=a[i];s=sqrt(x);        for(j=1;p[j]<=s;j++)        if(!(x%p[j])){            c[i][++l[i]]=p[j];x/=p[j];            while(!(x%p[j]))x/=p[j];        }        if(x>1)c[i][++l[i]]=x;    }    memset(b,0,sizeof(b));    while(q--){        Read(x);        if(!b[x])Update(x,1),b[x]=1;        else Update(x,-1),b[x]=0;        Print(Ans);    }    return 0;}