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

 

你可能感兴趣的:(code)