快速沃尔什变换

创建时间:2026-02-04


快速沃尔什变换

快速沃尔什变换(Fast Walsh–Hadamard Transform, FWT)是一种处理特殊的“多项式乘法”的算法。

以异或为例,现在给定 \(2\) 的正整数次幂 \(n\) 和长度为 \(n\) 的 0-index 序列 \(A = \{a_0, a_1, a_2, \cdots, a_{n-1}\}, B = \{b_0, b_1, b_2, \cdots, b_{n-1}\}\),试求序列 \(C = \{c_0, ,c_1, c_2, \cdots, c_{n-1}\}\),其中:

\[c_i = \sum_{j \oplus k} a_j b_k \]

直接暴力做是 \(O(n^2)\) 的。考虑构造一种变换,将序列 \(A\) 变换为 \(\mathrm{FWT_{xor}}(A)\),使得

\[\mathrm{FWT_{xor}}(C)[i] = \mathrm{FWT_{xor}}(A)[i] \times \mathrm{FWT_{xor}}(B)[i] \]

如果我们能快速求出 \(\mathrm{FWT_{xor}}(A), \mathrm{FWT_{xor}}(B)\),并由 \(\mathrm{FWT_{xor}}(C)\) 求出 \(C\),就能快速完成“多项式乘法”。

下面给出异或运算中 \(\mathrm{FWT_{xor}}\) 的定义:记
\(x \circ y = \text{popcount}(x \& y) \bmod 2\)

\[\mathrm{FWT_{xor}}(A)[i] = \sum_{i \circ j = 0} a_j - \sum_{i \circ j = 1} a_j \]

其中 \(\mathrm{popcount}(x)\)\(x\) 在二进制下 \(1\) 的个数,\(\&\) 是按位与运算。

\(n \ge 2\) 时,构造 \(A_0 = \{a_0, a_1, a_2, \cdots, a_{\frac n 2 - 1}\}, A_1 = \{a_{\frac n 2}, a_{\frac n 2 + 1}, a_{\frac n 2 + 2}, \cdots, a_{n-1}\}\),记 \((X, Y)\) 为将序列 \(Y\) 拼接在 \(X\) 后面,根据数学推导:

\[\mathrm{FWT_{xor}}(A) = (\mathrm{FWT_{xor}}(A_0) + \mathrm{FWT_{xor}}(A_1), \mathrm{FWT_{xor}}(A_0) - \mathrm{FWT_{xor}}(A_1)) \]

故可以通过分治求出 \(\mathrm{FWT_{xor}}(A)\),进一步得到 \(\mathrm{FWT_{xor}}(B), \mathrm{FWT_{xor}}(C)\)

\(\mathrm{IFWT_{xor}}(A)\)\(\mathrm{FWT_{xor}}(A)\) 的逆运算。形式化的,设 \(A' = \mathrm{FWT_{xor}}(A)\),那么 \(\mathrm{IFWT_{xor}}(A') = A\)。由上面求 FWT 的式子解方程,得:

\[\mathrm{IFWT_{xor}}(A') = (\frac{\mathrm{IFWT_{xor}}(A'_0) + \mathrm{IFWT_{xor}}(A'_1)} 2, \frac{\mathrm{IFWT_{xor}}(A'_0) - \mathrm{IFWT_{xor}}(A'_1)} 2) \]

代码:

void fwt(int a[], int tot) {
    for (int i = 1; i < tot; i *= 2)
        for (int j = 0; j < tot; j += i * 2)    
            for (int k = j; k < j + i; k++) {
                int x = a[k], y = a[k + i];
                a[k] = (x + y) % mod;
                a[k + i] = (x - y + mod) % mod;
            }
}

void ifwt(int a[], int tot) {
    for (int i = 1; i < tot; i *= 2)
        for (int j = 0; j < tot; j += i * 2)
            for (int k = j; k < j + i; k++) {
                int x = a[k], y = a[k + i];
                a[k] = 1ll * (x + y) * inv2 % mod;
                a[k + i] = 1ll * (x - y + mod) * inv2 % mod;
            }
}

类似的,我们有:

\[\mathrm{FWT_{or}}(A)[i] = \sum_{i | j = i} a_j \]

\[\mathrm{FWT_{and}}(A)[i] = \sum_{i \& j = i} a_j \]

\[\mathrm{FWT_{or}}(A) = (\mathrm{FWT_{or}}(A_0), \mathrm{FWT_{or}}(A_0) + \mathrm{FWT_{or}}(A_1)) \]

\[\mathrm{IFWT_{or}}(A') = (\mathrm{IFWT_{or}}(A'_0), \mathrm{IFWT_{or}}(A'_1) - \mathrm{IFWT_{or}}(A'_0)) \]

\[\mathrm{FWT_{and}}(A) = (\mathrm{FWT_{and}}(A_0) + \mathrm{FWT_{and}}(A_1), \mathrm{FWT_{and}}(A_1)) \]

\[\mathrm{IFWT_{and}}(A') = (\mathrm{IFWT_{and}}(A'_0) - \mathrm{IFWT_{and}}(A'_1), \mathrm{IFWT_{and}}(A'_1)) \]

正确性证明

下面只证明异或运算下快速沃尔什变换的正确性。

首先易知,\((x \circ y) \oplus (x \circ z) = x \circ (y \oplus z)\),所以

\[\begin{aligned} & \mathrm{FWT_{xor}}(A)[i] \times \mathrm{FWT_{xor}}(B)[i] \\ &= (\sum_{i \circ j = 0} a_j - \sum_{i \circ j = 1} a_j) (\sum_{i \circ k = 0} b_k - \sum_{i \circ k = 1} b_k) \\ &= (\sum_j (-1)^{i \circ j} a_j) (\sum_k (-1)^{i \circ k} b_k) \\ &= \sum_j \sum_k (-1)^{(i \circ j) \oplus (i \circ k)} a_j b_k \\ &= \sum_j \sum_k (-1)^{i \circ (j \oplus k)} a_j b_k \\ &= \sum_t (-1)^{i \circ t} \sum_{j \oplus k = t} a_j b_k \\ &= \sum_t (-1)^{i \circ t} c_t \\ &= \mathrm{FWT_{xor}}(C)[i] \end{aligned}\]

事实上,我们可以构造矩阵 \(Mat\),使得 \(Mat_{i, j} Mat_{i, k} = Mat_{i, j \oplus k}\)。下面是满足条件的 \(Mat\)

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

求出其逆矩阵

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

发现与 FWT、IWFT 的过程中的系数完全吻合!

应用

容易证明,

\[\mathrm{FWT}(A) \pm \mathrm{FWT}(B) = \mathrm FWT(A \pm B) \]

posted @ 2026-06-02 16:55  xubaichuan  阅读(8)  评论(0)    收藏  举报