codeforeces 547C

题目:给出若干数,然后若干组询问,每次询问一个数,如果这个数存在,那么删去这个数,如果没有,添加这个数,每次询问后输出此时已经有的数中互质的有多少对。

思路:利用容斥原理求出已经有的数中与正在询问的数不互质的数的数目。先对所有数进行质数分解。然后通过含有的不同质数对所有数字进行分类。之后就可以用容斥原理统计数目。因为质数的数目实际上不大(每个数的质因子数目实际上很小)所以此类题可以直接用dfs。

PS:此题暴露出了在数学题上的若干细节问题,改了一上午。。。

#include<iostream>
#include<map>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<queue>
#include<stack>
#include<functional>
#include<set>
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<ll,ll> P;
const int maxv=5e5+400;
vector<int> G[maxv];
vector<int> pri;
bool p[maxv];
set<int> beer;
int f[maxv],c[maxv],a[maxv];
int n,q;
void init(){
    for(int i=2;i<maxv;i++){
        if(!p[i]) pri.pb(i);
        for(int j=0;j<pri.size()&&i*pri[j]<maxv;j++){
            p[i*pri[j]]=1;
            if(i%pri[j]==0) break;
        }
    }
}
void getp(){
    for(int i=0;i<n;i++){
        int x=a[i];
        int h=0;
        while(x>1&&pri[h]*pri[h]<=x){
            if(x%pri[h]==0){
                G[i].pb(pri[h]);
                while(x>1&&x%pri[h]==0) x/=pri[h];
            }
            h++;
        }
        if(x!=1) G[i].pb(x);
    }
}
void read(){
    cin>>n>>q;
    for(int i=0;i<n;i++) scanf("%d",a+i);
}
ll ans=0;
int top=0;
void dfs(int t,int x,int cont,int flag,int val){
    if(t>=(int)G[x].size()){
        if(cont==0) return;
        ans+=f[val]*flag;
        c[top++]=val;
        return;
    }
    dfs(t+1,x,cont,flag,val);
    dfs(t+1,x,cont+1,flag*-1,val*G[x][t]);
}
void solve(){
    int x;
    while(q--){
        scanf("%d",&x);
        x--;
        if(a[x]==1){
            if(beer.find(x)!=beer.end()){
                beer.erase(x);
                ans-=beer.size();
            }else{
                ans+=beer.size();
                beer.insert(x);
            }
        }else{
            if(beer.find(x)!=beer.end()){
                beer.erase(x);
                ans-=beer.size();
                top=0;
                dfs(0,x,0,-1,1);
                ans--;
                beer.erase(x);
                for(int i=0;i<top;i++) f[c[i]]--;
            }else{
                top=0;
                ans+=beer.size();
                dfs(0,x,0,1,1);
                beer.insert(x);
                for(int i=0;i<top;i++) f[c[i]]++;
            }
        }
        printf("%lld\n",ans);
    }
}
int main(){
    //freopen("/home/files/CppFiles/in","r",stdin);
    init();
    read();
    getp();
    solve();
    return 0;
}
View Code

 

posted @ 2015-07-13 14:20  PlusSeven  阅读(198)  评论(0编辑  收藏  举报