CF2096H Wonderful XOR Problem 题解

Description

nn 个区间 [l1,r1],[l2,r2],[ln,rn][l_1, r_1], [l_2, r_2], \ldots [l_n, r_n]。对于每个 xx002m12^m - 1,求满足以下条件的序列 a1,a2,ana_1, a_2, \ldots a_n 的数量(模 998244353998\,244\,353):

  • 对于所有 ii11nn,有 liairil_i \leq a_i \leq r_i
  • a1a2an=xa_1 \oplus a_2 \oplus \ldots \oplus a_n = x,其中 \oplus 表示按位异或运算符

1n2×105,1m181\leq n\leq 2\times 10^5,1\leq m\leq 18

Solution

显然是 fwt。考虑求出 [li,ri][l_i,r_i] 对应的 fwt 数组。设 pc(x)=popcount(x)\text{pc}(x)=\text{popcount}(x)

先把 [li,ri][l_i,r_i] 变成 [0,ri][0,li1][0,r_i]-[0,l_i-1],现在问题变为求出 i=0n(1)pc(x&i)\sum_{i=0}^{n}{(-1)^{\text{pc}(x\&i)}}

现在把 xx 的 lowbit 拿出来,假设为 2b2^b,那么对于所有 iibb 位之前没有顶到 nn 的上界的所有数,由于 bb 位的存在,一定会互相抵消。

然后再分讨一下可以发现答案为 (1)pc(n&x)[nmod2b+1(n&2b)](-1)^{\text{pc}(n\&x)}\left[n\bmod 2^b+1-(n\&2^b)\right],设 vb,n=nmod2b+1(n&2b)v_{b,n}=n\bmod 2^b+1-(n\&2^b)

那么 fwtx=i=1n[(1)pc(ri&x)vb,ri(1)pc((li1)&x)vb,li1]\displaystyle fwt_x=\prod_{i=1}^{n}{\left[(-1)^{\text{pc}(r_i\&x)}v_{b,r_i}-(-1)^{\text{pc}((l_i-1)\&x)}v_{b,l_i-1}\right]}

容易想到枚举 bb,每次求上面的那个东西,再化简一下:

fwtx=i=1n[(1)pc(ri&x)vb,ri(1)pc((li1)&x)vb,li1]=i=1n[(1)pc((li1)&x)vb,li1(1+vb,rivb,li1(1)pc(ri&x)+pc((li1)&x))]=i=1n[(1)pc((li1)&x)vb,li1(1+vb,rivb,li1(1)pc((ri(li1))&x))]\begin{aligned} fwt_x=&\prod_{i=1}^{n}{\left[(-1)^{\text{pc}(r_i\&x)}v_{b,r_i}-(-1)^{\text{pc}((l_i-1)\&x)}v_{b,l_i-1}\right]}\\ =&\prod_{i=1}^{n}{\left[(-1)^{\text{pc}((l_i-1)\&x)}v_{b,l_i-1}\cdot\left(-1+\frac{v_{b,r_i}}{v_{b,l_i-1}}\cdot(-1)^{pc(r_i\&x)+pc((l_i-1)\&x)}\right)\right]}\\ =&\prod_{i=1}^{n}{\left[(-1)^{\text{pc}((l_i-1)\&x)}v_{b,l_i-1}\cdot\left(-1+\frac{v_{b,r_i}}{v_{b,l_i-1}}\cdot(-1)^{pc((r_i\oplus(l_i-1))\&x)}\right)\right]}\\ \end{aligned}

那个小括号外面的部分可以直接用类似 fwt 的东西做。小括号里面的东西是形如 (ai+bixci)\displaystyle\prod(a_i+b_ix^{c_i}) 的东西,也是个经典技巧,设 fwtx,0/1fwt_{x,0/1} 表示目前 (ai+bixci)\displaystyle\prod\left(a_i+b_ix^{c_i}\right) 的乘积和 (aibixci)\displaystyle\prod\left(a_i-b_ix^{c_i}\right),具体转移看代码。

时间复杂度:O(nm+2mm)O(nm+2^m\cdot m)

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <bits/stdc++.h>

// #define int int64_t

const int kMaxN = 3e5 + 5, kMod = 998244353;

int n, m;
int l[kMaxN], r[kMaxN], f[kMaxN];

int qpow(int bs, int64_t idx = kMod - 2) {
int ret = 1;
for (; idx; idx >>= 1, bs = (int64_t)bs * bs % kMod)
if (idx & 1)
ret = (int64_t)ret * bs % kMod;
return ret;
}

inline int add(int x, int y) { return (x + y >= kMod ? x + y - kMod : x + y); }
inline int sub(int x, int y) { return (x >= y ? x - y : x - y + kMod); }
inline void inc(int &x, int y) { (x += y) >= kMod ? x -= kMod : x; }
inline void dec(int &x, int y) { (x -= y) < 0 ? x += kMod : x; }
inline int getop(int x) { return (~x & 1) ? 1 : (kMod - 1); }

void ifwt(int *f, int n) {
static const int kInv2 = (kMod + 1) / 2;
for (int i = 0; i < n; ++i) {
int m = (1 << i), len = 2 * m;
for (int b = 0; b < (1 << n); b += len) {
for (int j = b; j < b + m; ++j) {
int val = f[j];
f[j] = 1ll * kInv2 * add(val, f[j | m]) % kMod;
f[j | m] = 1ll * kInv2 * sub(val, f[j | m]) % kMod;
}
}
}
}

void dickdreamer() {
std::cin >> n >> m;
for (int i = 1; i <= n; ++i) std::cin >> l[i] >> r[i];
for (int bb = 0; bb < m; ++bb) {
static int fwt[kMaxN][2];
int mm = m - bb;
for (int i = 0; i < (1 << mm); ++i) fwt[i][0] = fwt[i][1] = 1;
int coef = 1;
for (int i = 1; i <= n; ++i) {
int vl = 0, vr = sub((r[i] & ((1 << bb) - 1)) + 1, (r[i] & (1 << bb)));
if (l[i]) vl = sub(((l[i] - 1) & ((1 << bb) - 1)) + 1, (l[i] - 1) & (1 << bb));
int a, b, c;
if (vl) {
coef = 1ll * coef * vl % kMod;
a = kMod - 1, b = 1ll * vr * qpow(vl) % kMod, c = ((r[i] ^ (l[i] - 1)) >> bb);
fwt[(l[i] - 1) >> bb][1] = sub(0, fwt[(l[i] - 1) >> bb][1]);
} else {
a = 0, b = vr, c = (r[i] >> bb);
}
fwt[c][0] = 1ll * fwt[c][0] * add(a, b) % kMod;
fwt[c][1] = 1ll * fwt[c][1] * sub(a, b) % kMod;
}
for (int i = 0; i < mm; ++i) {
int m = (1 << i), len = 2 * m;
for (int k = 0; k < (1 << mm); k += len) {
for (int j = k; j < k + m; ++j) {
int tmp[2] = {fwt[j][0], fwt[j][1]}, tmp1[2] = {fwt[j | m][0], fwt[j | m][1]};
fwt[j][0] = 1ll * tmp[0] * tmp1[0] % kMod;
fwt[j][1] = 1ll * tmp[1] * tmp1[1] % kMod;
fwt[j | m][0] = 1ll * tmp[0] * tmp1[1] % kMod;
fwt[j | m][1] = 1ll * tmp[1] * tmp1[0] % kMod;
}
}
}
for (int i = 1; i < (1 << mm); i += 2) {
f[i << bb] = 1ll * coef * fwt[i][0] % kMod;
}
}
f[0] = 1;
for (int i = 1; i <= n; ++i) f[0] = 1ll * f[0] * (r[i] - l[i] + 1) % kMod;
ifwt(f, m);
int res = 0;
for (int i = 0; i < (1 << m); ++i) res ^= (1ll * f[i] * qpow(2, i) % kMod);
std::cout << res << '\n';
}

int32_t main() {
#ifdef ORZXKR
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0);
int T = 1;
std::cin >> T;
while (T--) dickdreamer();
// std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n";
return 0;
}

CF2096H Wonderful XOR Problem 题解
https://sobaliuziao.github.io/2025/07/30/post/d522ffeb.html
作者
Egg_laying_master
发布于
2025年7月30日
许可协议