codeforces #305 C Mike and Foam
首先我们注意到ai<=50w
因为2*3*5*7*11*13*17=510510
所以其最多含有6个质因子
我们将每个数的贡献分离,
添加就等于加上了跟这个数相关的互素对
删除就等于减去了跟这个数相关的互素对
问题转化为了求跟某个数相关的互素对的数目
我们可以用容斥来解决
即加上至少跟这个数有0个公共质因子的数
减去至少跟这个数有1个公共质因子的数
加上至少跟这个数又2个公共质因子的数……
这样我们就可以在2^6的时间算出答案了
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<vector> #include<cmath> using namespace std; typedef long long LL; const int maxn=200010; int n,m,x,tot; int a[maxn]; bool check[maxn]; vector<int>V[maxn]; int p[500010],cnt=0; bool vis[500010]; int Num[500010]; LL ans=0; void Get_Prime(){ for(int i=2;i<=500000;++i){ if(!vis[i])p[++cnt]=i; for(int j=1;j<=cnt;++j){ if(1LL*p[j]*i>500000)break; vis[p[j]*i]=true; if(i%p[j]==0)break; } }return; } void push(int now){ int x=a[now],lim=(int)(sqrt(x)); for(int i=1;i<=cnt;++i){ if(p[i]>lim)break; if(x%p[i]==0){ V[now].push_back(p[i]); while(x%p[i]==0)x/=p[i]; if(x==1)break; } } if(x>1)V[now].push_back(x); } void add(int now){ int k=V[now].size(); for(int i=0;i<(1<<k);++i){ int bit=0,o=1; for(int j=0;j<k;++j)if(i>>j&1)bit++,o*=V[now][j]; if(bit&1)ans-=Num[o]; else ans+=Num[o]; Num[o]++; }return; } void del(int now){ int k=V[now].size(); for(int i=0;i<(1<<k);++i){ int bit=0,o=1; for(int j=0;j<k;++j)if(i>>j&1)bit++,o*=V[now][j]; Num[o]--; if(bit&1)ans+=Num[o]; else ans-=Num[o]; }return; } int main(){ scanf("%d%d",&n,&m); Get_Prime(); for(int i=1;i<=n;++i)scanf("%d",&a[i]),push(i); for(int i=1;i<=m;++i){ scanf("%d",&x); if(check[x])del(x),check[x]=false; else add(x),check[x]=true; cout<<ans<<endl; }return 0; }