codeforces548E Mike and Foam -- 容斥

先对所有数质因数分解。显然相同的质因数可以看成一个。这样一个数最多只有 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 long
inline 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值