您的位置:首页 > 其它

codeforces #305 C Mike and Foam

2016-04-04 21:05 483 查看
首先我们注意到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;

}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: