在一个集合中,找和x互素的数有多少?
用容斥定理,先把每个数质因数分解(每个数至多有6个质因子),奇减偶加,就统计到和x互素的数了。
代码:
#include<iostream> #include<vector> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; const int N = 5*100000+10; const int maxn = 5*100000; int cnt[N],pri[N],vis[N],num; vector<int> gc[N]; void init(){ memset(cnt,0,sizeof(cnt)); for(int i=0;i<=maxn;i++) gc[i].clear(); for(int i=2;i<=maxn;i++) if(gc[i].size()==0) for(int j=i;j<=maxn;j+=i) gc[j].push_back(i); } void add(int x,int y){ int size = gc[x].size(); for(int i=0;i<(1<<size);i++){ int tmp=1; for(int j=0;j<size;j++) if(i&(1<<j)){ tmp *= gc[x][j]; } cnt[tmp] += y; } } int cal(int x){ int ans = 0; int size = gc[x].size(); for(int i=0;i<(1<<size);i++){ int tmp = 1, fl = 1; for(int j=0;j<size;j++) if(i&(1<<j)){ tmp *= gc[x][j]; fl *= -1; } ans += fl*cnt[tmp]; } // printf("hehe %d\n",ans); return ans; } int a[N],fl[N]; int main(){ int n,q,x; cin >> n >> q; init(); memset(fl,0,sizeof(fl)); long long ans = 0; for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=q;i++){ scanf("%d",&x); if(!fl[x]){ ans += cal(a[x]); add(a[x],1); fl[x] = 1; } else{ add(a[x],-1); ans -= cal(a[x]); fl[x] = 0; } printf("%I64d\n",ans); } return 0; }
时间: 2024-10-05 07:52:35