题意:给出数组arr和一个空数组dst。从arr中取出一个元素到dst为一次操作。问每次操作后dst数组中gcd等于1的组合数。
由于数据都小于10^6,先将10^6以下的数分解质因数。具体来说从2开始,将2的倍数全部加2因子(用的vector),3的倍数加3因子。4不是质数,它的倍数不加因子。
还要一个cnt数组记录dst中有几个数是数组下标的倍数。
在放入元素x到dst数组,对于它的每个质因数及质因数间的乘积,看cnt中的量。组合数的增量为dst的sz(size)-(cnt[x的质因数])(即dst中和x都有x的质因数,因此要减)+(cnt[x的两个质因数的乘积])......然后再对x的素因子及成绩在cnt上加1.
乱码:
//#pragma comment(linker,"/STACK:1024000000,1024000000") #include<iostream> #include<cstdio> #include<string> #include<cstring> #include<vector> #include<cmath> #include<queue> #include<stack> #include<map> #include<set> #include<algorithm> #include <stack> #include <list> using namespace std; const int SZ=1000010,INF=0x7FFFFFFF; typedef long long lon; const double EPS=1e-9; vector<lon> fen[SZ]; bool used[SZ]; lon cnt[SZ]; void init(lon n) { for(int i=2;i<n;++i) { if(fen[i].empty()) for(int j=i;j<n;j+=i) { fen[j].push_back(i); } } } void add(vector<lon> &vct,bool type) { lon sz=vct.size(); for(lon i=0;i<(1<<sz);++i) { lon res=1; for(lon j=0;j<6;++j) { if(i&(1<<j)) { res*=vct[j]; } } if(type)++cnt[res]; else --cnt[res]; } } lon work(vector<lon> &vct) { lon ans=0; lon sz=vct.size(); //cout<<" "<<sz<<endl; for(lon i=1;i<(1<<sz);++i) { lon res=1; lon co=1; for(lon j=0;j<6;++j) { if(i&(1<<j)) { res*=vct[j]; co*=-1; } } ans+=co*cnt[res]; } return ans; } int main() { std::ios::sync_with_stdio(0); //freopen("d:\\1.txt","r",stdin); lon n,m; cin>>n>>m; vector<lon> vct(n); for(int i=0;i<n;++i) { cin>>vct[i]; } init(5e5+10); lon num=0; lon last=0; for(int i=0;i<m;++i) { lon id; cin>>id; --id; lon res=0; if(!used[id]) { res+=work(fen[vct[id]]); //cout<<" "<<res<<endl; add(fen[vct[id]],1); used[id]=1; res=last+res+num; } else { res=last; add(fen[vct[id]],0); lon val=work(fen[vct[id]]); //cout<<" "<<val<<endl; res-=num-1+work(fen[vct[id]]); //cout<<" "<<res<<endl; used[id]=0; } cout<<res<<endl; if(used[id])++num; else --num; last=res; } return 0; }