Loading

$\text{FWT}$ 快速沃尔什变换学习笔记

\(\text{FWT}\) 快速沃尔什变换

给定两个序列 \(a,b\) ,求解序列 \(c\) 满足:

\[c_i=\sum_{j\cdot k=i}a_jb_k \]

其中 \(\cdot\) 可以为 \(\&\)\(|\) ,还有 \(\oplus\) 等位运算。快速沃尔什变换用于求解位运算卷积等问题。

\(\text{and}\)\(\text{or}\) 卷积

\(\text{or}\) 为例

\[FWT(a)_i=\sum_{j|i=i}a_j \]

\[FWT(c)_i=FWT(a)_iFWT(b)_i=\sum_{j|i=i}a_i\sum_{k|i=i}b_k=\sum_{(j|k)|i=i}a_jb_k \]

那么我们只要完成 \(a \rightarrow FWT(a)\)\(FWT(a) \rightarrow a\) 这两种操作即可。

先考虑前者,分治处理,将 \(a\) 序列中按照下标最高位分类。记 \(a_0\) 为最高位为 \(0\) 的那一部分,\(a_1\) 为最高位为 \(1\) 的那一部分,考虑合并的过程:

\[FWT(a)=merge(FWT(a_0),FWT(a_0)+FWT(a_1)) \]

\(merge\) 表示将两个序列拼接,\(+\) 表示对应位相加。其原理是 \(a_0\) 中的每一位都是其在 \(a_1\) 中的子集,需要做贡献。

那么第二种操作就是将上述分治过程逆过来即可:

\[a=merge(a_0,a_1-a_0) \]

再来考虑 \(\text{and}\)

\[FWT(a)_i=\sum_{j \& i=i}a_j \]

\[FWT(a)=merge(a_0+a_1,a_1) \]

\[a=merge(a_0-a_1,a_1) \]

\(\text{xor}\) 卷积

这里记

\[FWT(a)_i=\sum_{j\oplus i=0}a_j-\sum_{j \oplus i=1}a_j \]

其中 \(j\oplus i=popcount(j \& i)\&1\) ,考虑每一位对答案的贡献,不难发现满足:

\[(j \oplus i)\: \text{xor}\: (k \oplus i)=(j \: \text{xor} \:k)\oplus i \]

因此:

\[FWT(c)=FWT(a)FWT(b)=\left( \sum_{j \oplus i=0}a_j-\sum_{j\oplus i=1}a_j \right )\left( \sum_{k\oplus i=0}b_k-\sum_{k \oplus i=1}b_k\right) \]

\[=\sum_{(j\:\text{xor} \: k)\oplus i=0}a_jb_k-\sum_{(j \: \text{xor} \:k)\oplus i=1}a_jb_k \]

两部分求解过程依然是考虑分治与还原。

\[FWT(a)=merge(FWT(a_0)+FWT(a_1),FWT(a_0)-FWT(a_1)) \]

\[a=merge\left(\frac{a_0+a_1}{2},\frac{a_0-a_1}{2}\right) \]

然后到这里就做完了!

posted @ 2023-02-14 19:08  _YangZJ  阅读(43)  评论(1)    收藏  举报