可以对于每个可重集维护一个 bitset ,第
i
i
i 个集合的 bitset 第
j
j
j 位表示第
i
i
i 个集合中
j
j
j 的出现次数的奇偶性
但我们发现这样做无法解决第
3
3
3 种操作
我们不妨把维护的东西换一下
A
[
i
]
[
j
]
A[i][j]
A[i][j] 表示第
i
i
i 个集合内
j
j
j 的倍数的个数的奇偶性
对于
1
1
1 操作,直接将所有
v
v
v 的约数
k
k
k 令
A
[
v
]
[
k
]
=
1
A[v][k]=1
A[v][k]=1 ,其他的
k
k
k 把
A
[
v
]
[
k
]
A[v][k]
A[v][k] 改成
0
0
0 即可
对于
2
2
2 操作显然还是
A
[
x
]
←
A
[
y
]
⨁
A
[
z
]
A[x]\leftarrow A[y]\bigoplus A[z]
A[x]←A[y]⨁A[z] ,其中
⨁
\bigoplus
⨁ 为异或运算
对于
3
3
3 操作,显然
x
∣
gcd
(
a
,
b
)
x|\gcd(a,b)
x∣gcd(a,b) 当且仅当
x
∣
a
x|a
x∣a 且
x
∣
b
x|b
x∣b 。于是
A
[
x
]
←
A
[
y
]
&
A
[
z
]
A[x]\leftarrow A[y]\& A[z]
A[x]←A[y]&A[z] ,
&
\&
& 为与运算
而对于
4
4
4 ,我们如何在知道
A
[
x
]
A[x]
A[x] 的情况下知道第
x
x
x 个集合中
v
v
v 的个数的奇偶性呢?
对于
A
[
x
]
A[x]
A[x] ,进行莫比乌斯反演,得
a
n
s
=
∑
v
∣
k
A
[
x
]
[
k
]
μ
(
k
v
)
ans=\sum_{v|k}A[x][k]\mu(\frac kv)
ans=v∣k∑A[x][k]μ(vk)
再开 bitset
μ
[
v
]
[
k
]
\mu[v][k]
μ[v][k] 表示:如果
v
∣
k
v|k
v∣k 则
μ
[
v
]
[
k
]
=
∣
μ
(
k
v
)
∣
\mu[v][k]=|\mu(\frac kv)|
μ[v][k]=∣μ(vk)∣ ,否则
μ
[
v
]
[
k
]
=
0
\mu[v][k]=0
μ[v][k]=0
这样询问结果就是
A
[
x
]
&
m
u
[
v
]
A[x]\& mu[v]
A[x]&mu[v] 中
1
1
1 的个数的奇偶性
复杂度
O
(
(
n
+
q
+
v
)
v
64
)
O(\frac {(n+q+v)v}{64})
O(64(n+q+v)v)
Code
#include<bits/stdc++.h>inlineintread(){int res =0;bool bo =0;char c;while(((c =getchar())<'0'|| c >'9')&& c !='-');if(c =='-') bo =1;else res = c -48;while((c =getchar())>='0'&& c <='9')
res =(res <<3)+(res <<1)+(c -48);return bo ?~res +1: res;}constint N =1e5+5, M =7005;int n, q, miu[M], tot, pri[M];bool mark[M];
std::bitset<M> times[N], fy[M];voidsieve(){
mark[0]= mark[miu[1]=1]=1;for(int i =2; i <=7000; i++){if(!mark[i]) miu[pri[++tot]= i]=1;for(int j =1; j <= tot; j++){if(i * pri[j]>7000)break;
mark[i * pri[j]]=1;if(i % pri[j]==0)break;else miu[i * pri[j]]= miu[i];}}for(int i =1; i <=7000; i++)for(int j = i; j <=7000; j += i)
fy[i][j]= miu[j / i];}intmain(){
n =read(); q =read();sieve();int op, x, y, z;while(q--){
op =read(); x =read(); y =read();if(op ==1){int S =sqrt(y);
times[x]=0;for(int i =1; i <= S; i++){if(y % i)continue;
times[x][i]= times[x][y / i]=1;}}elseif(op ==2) z =read(), times[x]= times[y]^ times[z];elseif(op ==3) z =read(), times[x]= times[y]& times[z];elseprintf("%d",(times[x]& fy[y]).count()&1);}returnputs(""),0;}