【CF1097F】Alex and a TV Show
题面
题解
我们对于某个集合中的每个(i),令(f(i))表示(i)作为约数出现次数的奇偶性。
因为只要因为奇偶性只有(0,1)两种,我们考虑用(bitset)维护这个(f)。
那么,
对于(1)操作你可以预处理一下(v)的(bitset),
对于(2)操作就是两个集合的(bitset)异或一下,
对于(3)操作就是两个集合的(bitset)与一下。
最后我们要由(f(i))推回(i)的出现次数,记为(g(i)),显然有
[f(n)=sum_{d|n} g(d)
]
莫比乌斯反演一下,
[g(n)=sum_{n|d} mu (frac dn) f(d)
]
你对于每个(n)把(n|d)的(mu (frac dn)mod 2)预处理出来放在一个(bitset)就好了。
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <bitset>
using namespace std;
inline int gi() {
register int data = 0, w = 1;
register char ch = 0;
while (!isdigit(ch) && ch != '-') ch = getchar();
if (ch == '-') w = -1, ch = getchar();
while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar();
return w * data;
}
const int MAX_N = 1e5 + 5, MAX_M = 7005;
bitset<MAX_M> bs[MAX_N], fact[MAX_M], mu[MAX_M], m;
int N = 7000, Q;
void Prepare() {
m.set();
for (int i = 2; i * i <= N; i++)
for (int j = i * i; j <= N; j += i * i) m[j] = 0;
for (int i = 1; i <= N; i++)
for (int j = i; j <= N; j += i) fact[j][i] = 1, mu[i][j] = m[j / i];
}
int main () {
#ifndef ONLINE_JUDGE
freopen("cpp.in", "r", stdin);
#endif
Prepare();
N = gi(), Q = gi();
while (Q--) {
int op = gi(), x = gi(), y = gi(), z;
if (op == 1) bs[x] = fact[y];
if (op == 2) z = gi(), bs[x] = bs[y] ^ bs[z];
if (op == 3) z = gi(), bs[x] = bs[y] & bs[z];
if (op == 4) printf("%lu", (bs[x] & mu[y]).count() & 1);
}
return 0;
}