题意:
给定 n n n 个空的 m u l t i s e t multiset multiset,有四种操作:① 1 , x , v 1, x, v 1,x,v,表示将第 x x x 个集合赋为 { v ~v~ v };② 2 , x , y , z 2, x, y, z 2,x,y,z,令 x = y ∪ z x = y \cup z x=y∪z;③ 3 , x , y , z 3, x, y, z 3,x,y,z,令 x = y R z x = y~R~z x=y R z, R = { g c d ( a , b ) ∣ a ∈ y , b ∈ z } R=\{gcd(a,b)\mid a \in y, b \in z\} R={gcd(a,b)∣a∈y,b∈z};④ 4 , x , v 4, x, v 4,x,v,询问集合 x x x 中 v v v 出现次数的奇偶性。 ( n ≤ 1 0 5 , q ≤ 1 0 6 , v ≤ 7000 ) (n\leq10^5,~q\leq10^6,~v\leq7000) (n≤105, q≤106, v≤7000)
链接:
https://codeforces.com/contest/1097/problem/F
解题思路:
只需要得到结果的奇偶性,使用
b
i
t
s
e
t
bitset
bitset 操作。由于有 ③ 操作,涉及
g
c
d
gcd
gcd,即因子的操作,
b
s
[
x
]
[
i
]
bs[x][i]
bs[x][i] 中维护的是
i
i
i 作为
x
x
x 因子出现次数的奇偶性。预处理后,① 操作为赋值,② 操作为
b
i
t
s
e
t
bitset
bitset 相异或,③ 操作 为
b
i
t
s
e
t
bitset
bitset 相位与。
对于 ④ 操作:
令
f
(
x
)
f(x)
f(x) =
x
x
x 作为因子出现次数,
g
(
x
)
g(x)
g(x) =
x
x
x 出现次数,
则
f
(
n
)
=
∑
n
∣
d
g
(
d
)
f(n) = \sum\limits_{n|d}g(d)
f(n)=n∣d∑g(d)
进而
g
(
n
)
=
∑
n
∣
d
μ
(
d
n
)
f
(
d
)
g(n) = \sum\limits_{n|d}\mu(\frac{d}{n})f(d)
g(n)=n∣d∑μ(nd)f(d)
预处理出
μ
(
x
)
\mu(x)
μ(x) 对应的
b
i
t
s
e
t
bitset
bitset 即可。
参考代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define sz(a) ((int)a.size())
#define pb push_back
#define lson (rt << 1)
#define rson (rt << 1 | 1)
#define gmid (l + r >> 1)
const int maxn = 1e5 + 5;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
bitset<7005> a[maxn], val[7005], msk[7005];
int mu[7005], vis[7005], prime[7005];
int n, q, tot;
void init(){
mu[1] = 1, vis[1] = 1;
for(int i = 2; i <= 7000; ++i){
if(!vis[i]) prime[++tot] = i, mu[i] = -1;
for(int j = 1; j <= tot && i * prime[j] <= 7000; ++j){
vis[i * prime[j]] = 1;
if(i % prime[j]) mu[i * prime[j]] = -mu[i];
else { mu[i * prime[j]] = 0; break; }
}
}
for(int i = 1; i <= 7000; ++i){
for(int j = i; j <= 7000; j += i){
val[j][i] = 1;
if(mu[j / i]) msk[i][j] = 1;
}
}
}
int main(){
ios::sync_with_stdio(0); cin.tie(0);
init();
cin >> n >> q;
while(q--){
int opt, x, y, z; cin >> opt >> x >> y;
if(opt == 1){
a[x] = val[y];
}
else if(opt == 2){
cin >> z;
a[x] = a[y] ^ a[z];
}
else if(opt == 3){
cin >> z;
a[x] = a[y] & a[z];
}
else{
cout << ((a[x] & msk[y]).count() & 1);
}
}
return 0;
}