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;
	
}

  

 

posted @ 2016-04-04 21:05  _Vertical  阅读(355)  评论(0编辑  收藏  举报