Alex decided to try his luck in TV shows. He once went to the quiz named "What's That Word?!". After perfectly answering the questions "How is a pseudonym commonly referred to in the Internet?" ("Um... a nick?"), "After which famous inventor we name the unit of the magnetic field strength?" ("Um... Nikola Tesla?") and "Which rock band performs "How You Remind Me"?" ("Um... Nickelback?"), he decided to apply to a little bit more difficult TV show: "What's in This Multiset?!".
The rules of this TV show are as follows: there are n
multisets numbered from 1 to n. Each of them is initially empty. Then, q
events happen; each of them is in one of the four possible types:
- 1 x v — set the x
-th multiset to a singleton {v}
- 2 x y z — set the x
- 3 x y z — set the x
- 4 x v — the participant is asked how many times number v
- only.
Note, that x
, y and z described above are not necessarily different. In events of types 2 and 3, the sum or the product is computed first, and then the assignment is performed.
Alex is confused by the complicated rules of the show. Can you help him answer the requests of the 4
-th type?
InputThe first line contains two integers n
and q (1≤n≤105, 1≤q) — the number of multisets and the number of events.
Each of the following q
lines describes next event in the format given in statement. It's guaranteed that 1≤x,y and 1≤v≤7000always holds.
It's guaranteed that there will be at least one event of the 4
-th type.
OutputPrint a string which consists of digits 0
and 1 only, and has length equal to the number of events of the 4-th type. The i-th digit of the string should be equal to the answer for the i-th query of the 4-th type.
Example4 13 1 1 1 1 2 4 1 3 6 4 4 4 1 4 4 2 2 1 2 2 3 3 4 4 4 4 3 2 2 3 4 2 1 4 2 2 4 2 3 4 2 4
010101
Here is how the multisets look in the example test after each of the events; i
is the number of queries processed so far:
题意:
n个可重集,有Q次操作
1 u v 表示将第u个可重集的元素置为1个v
2 u a b 表示将第u个可重集置为第a个可重集和第b个可重集的并集
3 u a b 表示将第u个可重集置为第a个可重集的每个元素和第b个可重集的每个元素的gcd的并集
4 u v 表示求在第u个可重集中元素v的出现次数是奇数还是偶数
n<=1e5 Q<=1e6 1<=v<=7000
思路:由于是只要求奇数还是偶数,我们整个过程只需要保存0和1即可,我们用莫比乌斯来求是否存在一个gcd,即保存当前集合是因子的奇偶性。那么对于2和3,我们可以直接操作(分别是^ &)了。
假设我们知道了因子的数量的奇偶性,假设保存在s[]里面。 vis[gcd]=mu(d/gcd)*s[d];所以对于每个gcd,我们预处理出mu(d/gcd)!=0的位置d,保存到b[]里面。
由于只求奇偶,1和-1的效果等效,结果和s[x]*b[y]的1的数量奇偶相同;
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=100010; const int maxm=7001; bitset<maxm>s[maxn],b[maxm]; int mu[maxm],p[maxm],cnt;bool vis[maxm]; vector<int>G[maxm]; void init() { mu[1]=1; rep(i,2,maxm-1){ if(!vis[i]) p[++cnt]=i,mu[i]=-1; rep(j,1,cnt){ if(i*p[j]>=maxm) break; vis[i*p[j]]=1; if(!(i%p[j])) {mu[i*p[j]]=0; break;} mu[i*p[j]]=-mu[i]; } } rep(i,1,maxm-1) for(int j=i,k=1;j<=maxm-1;j+=i,k++){ G[j].push_back(i); if(mu[k]!=0) b[i][j]=1; } } int main() { int N,M,opt,x,y,z; init(); scanf("%d%d",&N,&M); while(M--){ scanf("%d",&opt); if(opt==1){ scanf("%d%d",&x,&y); s[x].reset(); rep(i,0,G[y].size()-1) s[x][G[y][i]]=s[x][G[y][i]]^1; } else if(opt==2){ scanf("%d%d%d",&x,&y,&z); s[x]=s[y]^s[z]; } else if(opt==3){ scanf("%d%d%d",&x,&y,&z); s[x]=s[y]&s[z]; } else { scanf("%d%d",&x,&y); if((s[x]&b[y]).count()&1) putchar('1'); else putchar('0'); } } return 0; }