FWT 学习笔记
高维前缀和(SOS DP)
https://www.cnblogs.com/heyuhhh/p/11585358.html
对于 \(i \in [0, 2^n - 1]\) 计算 \(\sum_{j \subset i} a_j\)
集合形式: \(\sum_{T \subseteq S} F(T)\)
我们考虑把每一位从 \(0\) 向 \(1\) 转移,设状态为 \(f_{i, S}\),表示已经考虑了前 \(i\) 位是 \(S\) 子集,其余位与 \(S\) 均相同的 \(T\) 的答案
则如果 \(S\) 第 \(i\) 位为 \(1\),那么 f[i][S] = f[i - 1][S] + f[i - 1][S ^ (1 << i)],否则,f[i][S] = f[i - 1][S]
滚掉一维,就变成常见的高维前缀和的形式
for (int i = 0; i < n; i++)
for (int s = 0; s < (1 << n); s++)
if (s & (1 << i))
f[s] += f[s ^ (1 << i)];
如果想要做逆变换,把加变成减就行了
这个东西也叫快速莫比乌斯变换(FMT),因为这个东西
其实叫莫比乌斯变换,然后有莫比乌斯反演,
类似的,我们也可以做高维后缀和,从 \(1\) 向 \(0\) 转移即可
FWT
可以做位运算卷积,\(c_k = \sum_{i \oplus j = k} a_i b_j\)
我们类比 FFT,考虑构造一种变换 \(FWT(A)\),使得 \(FWT(C)_i = FWT(A)_i \cdot FWT(B)_i\),这样我们就可以逐点相乘,然后再 \(IFWT\) 回去,就能快速计算了
DFT 是线性变换,考虑也构造一种线性变换 \(FWT\),设转移矩阵为 \(C\),那么
带入上面的点乘式子,容易得到 \(c(i, x) \times c(i, y) = c(i, x \oplus y)\)
同时,为了方便计算,我们可以加强这个 \(C\) 的性质,由于位运算可以按位考虑,我们考虑让 \(c_{i, j}\) 也可以按位考虑,即
其中 \(i_k\) 表示 \(i\) 的第 \(k\) 位
那么我们就可以像 FFT 一样递归计算了,
其中,\(i_0\) 表示 \(i\) 的最高位,\(i^\prime\) 表示去掉最高位后的 \(i\),\(A_0, A_1\) 分别表示 \(A[0, 2^{n-1}-1], A[2^{n-1}, 2^n-1]\),即 \(A\) 的前半段,后半段
于是乎,我们只需要知道 \(c(0, 0), c(0, 1), c(1, 0), c(1, 1)\),即矩阵
就行了,并且这四个数都满足上面 \(c(i, x) \times c(i, y) = c(i, x \oplus y)\) 这一条限制
对于逆变换,只需要把系数改为上面矩阵的逆就行了,所以构造出来的矩阵一定要有逆!
下面给出 or, and, xor 这三种运算常用的矩阵
- or
考虑组合意义,由于 \(c(i, j) = \prod c(i_k, j_k)\),而只有当 \(i_k=0, j_k=1\) 时系数为 \(0\),其余情况均为 \(1\),所以 \(c(i, j) = [j \subset i]\)
所以我们发现,or 卷积意义下的 FWT 相当于高维前缀和
- and
同样,我们发现 \(c(i, j) = [i \subset j]\),相当于高维后缀和
- xor
xor 的情况要有意思一点,我们发现只有当两位都是 \(1\) 时,系数为 \(-1\),所以就有
这里的 \(|\cdot|\) 代表 popcount,如果把 \(i, j\) 看成两个位向量,那么上式中的指数就是 \(i, j\) 的点积
由于 or, and 卷积分别对应高维前/后缀和,有时也将 FWT 定义为异或卷积下的 FWT,即
例题
核桃 XOR Sequence
对于一个序列 \(a_0, a_1, \cdots, a_{n-1}\),令 \(b_S = \mathrm{popcount}(\bigoplus_{x \in S} a_x)\),现给出所有 \(b_S\),构造出一组字典序最小的 \(\{a_i\}\),或报告无解
\(n \le 20, 0 \le a_i \le 2^{30}, 0 \le b_i \le 30\)
拆位考虑,
考虑设 \(c_k\) 为所有 \(a_i\) 的第 \(k\) 位按顺序排列组成的位向量,也就是说将所有 \(a_i\) 按二进制写成一列后排成一个矩阵,\(c_k\) 就是这个矩阵的第 \(k\) 行
考虑如果我们知道所有 \(c_k\),那么我们只需要按照字典序从大到小的顺序把这些位向量排到第 \(0 \sim 29\) 位上,就能得到字典序最小的解了
那么上式可以改写成 \(b_S = \sum_k \left[ c_k \cdot S \equiv 1 \pmod 2 \right]\)
考虑 \([x \equiv 1 \pmod 2] = \frac{1 - (-1)^x}{2}\),那么
是不是有一点 FWT 的感觉了?我们考虑记 \(w_x\) 表示有多少个 \(c_k = x\),那么就变成
就变成了标准的 FWT 形式,所以可以通过 IFWT 解出 \(w_c\),然后根据 \(c\) 之间的字典序关系就可以构造解了

浙公网安备 33010602011771号