除了操作
\(3\) 都可以
\(bitset\) 现在要维护
\[C_i=\sum_{gcd(j,k)=i}A_jB_k\] 类比
\(FWT\),只要求出
\(A'_i=\sum_{i|d}A_d\) 就可以直接按位相乘了
求答案就是莫比乌斯反演,
\(A_i=\sum_{i|d}\mu(\frac{d}{i})A'_i\) 把每个数字的
\(\mu\) 的
\(bitset\) 预处理出来,乘法就是
\(and\) 最后用
\(count\) 统计答案
# include using namespace std;typedef long long ll;const int maxn(7005);int mu[maxn], n, q, pr[maxn], tot;bitset bc[100005], bcm[7005], bcv[7005], ispr;int main() { int i, j, op, l, r, v; mu[1] = 1; for (i = 2; i <= 7000; ++i) { if (!ispr[i]) pr[++tot] = i, mu[i] = -1; for (j = 1; j <= tot && pr[j] * i <= 7000; ++j) { ispr[pr[j] * i] = 1; if (i % pr[j]) mu[i * pr[j]] = -mu[i]; else { mu[i * pr[j]] = 0; break; } } } for (i = 1; i <= 7000; ++i) for (j = i; j <= 7000; j += i) { bcv[j].set(i); if (mu[j / i]) bcm[i].set(j); } scanf("%d%d", &n, &q); for (i = 1; i <= q; ++i) { scanf("%d%d%d", &op, &l, &r); if (op == 1) bc[l] = bcv[r]; else if (op == 2) scanf("%d", &v), bc[l] = bc[r] ^ bc[v]; else if (op == 3) scanf("%d", &v), bc[l] = bc[r] & bc[v]; else putchar(((bc[l] & bcm[r]).count() & 1) + '0'); } return 0;}