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),因为这个东西

\[g(S) = \sum_{T \subseteq S} f(S) \]

其实叫莫比乌斯变换,然后有莫比乌斯反演,

\[f(S) = \sum_{T \subseteq S} (-1)^{|S| - |T|}g(T) \]

类似的,我们也可以做高维后缀和,从 \(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\),那么

\[FWT(A)_i = \sum_{j = 0}^{2^n-1} c(i, j) a_j \]

带入上面的点乘式子,容易得到 \(c(i, x) \times c(i, y) = c(i, x \oplus y)\)

同时,为了方便计算,我们可以加强这个 \(C\) 的性质,由于位运算可以按位考虑,我们考虑让 \(c_{i, j}\) 也可以按位考虑,即

\[c(i, j) = \prod_{k} c(i_k, j_k) \]

其中 \(i_k\) 表示 \(i\) 的第 \(k\)

那么我们就可以像 FFT 一样递归计算了,

\[\begin{aligned} FWT(A)_i &= \sum_{j} c(i, j) a_j \\ &= c(i_0, 0)\sum_{j < 2^{n-1}} c(i^\prime, j^\prime) a_j + c(i_0, 1)\sum_{j \ge 2^{n-1}} c(i^\prime, j^\prime) a_j \\ &= c(i_0, 0)\ FWT(A_0)_{i^\prime} + c(i_0, 1)\ FWT(A_1)_{i^\prime} \\ \end{aligned} \]

其中,\(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)\),即矩阵

\[\begin{bmatrix} c(0, 0) & c(0, 1) \\ c(1, 0) & c(1, 1) \end{bmatrix} \]

就行了,并且这四个数都满足上面 \(c(i, x) \times c(i, y) = c(i, x \oplus y)\) 这一条限制

对于逆变换,只需要把系数改为上面矩阵的逆就行了,所以构造出来的矩阵一定要有逆!

下面给出 or, and, xor 这三种运算常用的矩阵

  1. or

\[C = \begin{bmatrix} 1 & 0 \\ 1 & 1 \end{bmatrix} \]

\[C^{-1} = \begin{bmatrix} 1 & 0 \\ -1 & 1 \end{bmatrix} \]

考虑组合意义,由于 \(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 相当于高维前缀和

  1. and

\[C = \begin{bmatrix} 1 & 1 \\ 0 & 1 \end{bmatrix} \]

\[C^{-1} = \begin{bmatrix} 1 & -1 \\ 0 & 1 \end{bmatrix} \]

同样,我们发现 \(c(i, j) = [i \subset j]\),相当于高维后缀和

  1. xor

\[C= \begin{bmatrix} 1 & 1 \\ 1 & -1 \end{bmatrix} \]

\[C^{-1} = \begin{bmatrix} 0.5 & 0.5 \\ 0.5 & -0.5 \end{bmatrix} \]

xor 的情况要有意思一点,我们发现只有当两位都是 \(1\) 时,系数为 \(-1\),所以就有

\[c(i, j) = (-1)^{|i \& j|} \]

这里的 \(|\cdot|\) 代表 popcount,如果把 \(i, j\) 看成两个位向量,那么上式中的指数就是 \(i, j\) 的点积

由于 or, and 卷积分别对应高维前/后缀和,有时也将 FWT 定义为异或卷积下的 FWT,即

\[FWT(A)_i = \sum_{j} (-1)^{|i\& j|} a_j \]

例题

核桃 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\)

拆位考虑,

\[b_S = \sum_k \left[\sum_{i} i_k \equiv 1 \pmod 2\right] \]

考虑设 \(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}\),那么

\[30-2b_S = \sum_k (-1)^{c_k \cdot S} \]

是不是有一点 FWT 的感觉了?我们考虑记 \(w_x\) 表示有多少个 \(c_k = x\),那么就变成

\[30-2b_S = \sum_{c} (-1)^{c \cdot S} w_c \]

就变成了标准的 FWT 形式,所以可以通过 IFWT 解出 \(w_c\),然后根据 \(c\) 之间的字典序关系就可以构造解了

posted @ 2026-07-18 15:33  zhm0725  阅读(6)  评论(0)    收藏  举报