关于 FWT
FWT
FWT 的思想就是将数列经过变换后,将位运算卷积变为逐位相乘,最终通过逆变换将其得到所求数列。单次 FWT 的时间复杂度为 \(O(2^nn)\) 可以将 \(O(3^n)\) 甚至更高的卷积优化。
或卷积
有 \(C_s=\sum_{s=t|z}A_t\times B_z\) ,\(FWT(F)_s=\sum_{t \subseteq s}F_t\)。
可以发现 \(FWT\) 的变换就是求每个集合的子集和,这个东西是容易用高维前缀和做到 \(O(2^nn)\)。下面将证明它的正确性:
发现两边意义相同,证毕。
由于其良好的性质,计算单值时可以做到 \(O(2^n)\) ,简单容斥即可。
与卷积
和或卷积几乎同理。
异或卷积
有 \(C_s=\sum_{s=t\oplus z}A_t\times B_z\) ,\(FWT(F)_s=\sum_{t\circ s=0}F_t-\sum_{t\circ s=1}F_t\)。
(定义\(s\circ t=popcount(s\&t)(mod\ 2)\))
变换本身是容易的,直接依次考虑 \(2^i\) 的贡献即可,证明如下:
注意到有 \((x\oplus y)\circ s=(x\circ s)\oplus (y\circ s)\),所以式子左右两边相等。
子集卷积
子集卷积一般使用或卷积实现,在或卷积的基础上,再加上位数的限制就行了。时间复杂度会多一个 \(n\)。
深入
前面的叙述是肤浅的,不是很能参透FWT的本质。
其实所有变换的本质都是先求值再插值的一个过程,学习了集合幂级数后能够很好的认识到FWT的过程。
将FWT分成DWT和IDWT两个过程,拿异或卷积举例。
\(DWT(a)=\^{a_1},\^{a_2},\dots,\^{a_n}\) ,其中有 \(\^{a_S}=\sum (-1)^{|T\cap S|}a_T\)。
你可以发现,\(\^{a_s}\) 就是 \(a\) 序列的集合幂级数 \(A(x)\) 带入 \(x_i=(-1)^{[i\in s]}\)。
那么DWT是怎么求的?
在前面的学习中,我们知道DWT是分 \(n\) 层推的,其实就是从 \(1\sim n\) 去固定 \(x_i\)。

浙公网安备 33010602011771号