快速沃尔什变换也许是快速地求位运算卷积的一种方法。
给定序列 A 和 B ,求 C,满足 ci=i=j⊕k∑ajbk,其中 ⊕ 是某种运算。
与 FFT 一样, FWT 有几个流程,先将 A,B 变换为 FWT(A),FWT(B),再计算 FWT(C)i=FWT(A)i×FWT(B)i,最后将 FWT(C) 转换回 C。
总之,是 O(nlogn) — O(n) — O(nlogn) 的三步。
FWT 是根据不同的运算构造的。
or
即 Ci=i=j∣k∑ajbk
构造 FWT(A)i=j∣i=i∑aj
这样有
FWT(A)i×FWT(B)i=j∣i=i∑aj×k∣i=i∑bk=j∣i=i,k∣i=i∑ajbk=(j∣i)=i∑ajbk=FWT(C)i
求 FWT(A) 的过程可以考虑递归。
设 A0,A1 是A 的前半和后半部分,则 A0 与 A1 只有最高位的区别,A1 的子集一定包括 A0 的子集。
FWT(A)=merge(FWT(A0),FWT(A0)+FWT(A1)) ,其中 merge 是将两个序列拼接。
逆变换 IFWT(A)=merge(IFWT(A0),IFWT(A1)−IFWT(A0))
代码
咕咕咕
and
类似地,构造 FWT(A)=iandj=i∑ai。
有 FWT(A)=merge(FWT(A0)+FWT(A1),FWT(A1))。
IFWT(A)=merge(IFWT(A0)−IFWT(A1),IFWT(A1))
xor
重载运算符 x⊗y=(popcount(xxory))mod2 。
可以发现性质 没有性质我还要这运算符有何用 (x⊗y)xor(x⊗z)=x⊗(yxorz)
定义 FWT(A)i=i⊗j=0∑aj−i⊗j=1∑aj
然后推一推
FWT(A)i×FWT(B)i====(i⊗j=0∑aj−i⊗j=1∑aj)(i⊗k=0∑bk−i⊗k=1∑bk)i⊗j=0∑aji⊗k=0∑bk−i⊗j=1∑aji⊗k=0∑bk−i⊗j=0∑aji⊗k=0∑bk+i⊗j=1∑aji⊗k=1∑bki⊗(jxork)=0∑ajbk−i⊗(jxork)=1∑ajbkFWT(C)i
理解一下
考虑自底向上合并计算 FWT 的过程,每次考虑的是当前长度为 2x 的序列里的低 x 位,左边的部分最高位是 0, 右边部分最高位是 1,则有公式 FWT(A)=merge(FWT(A0)+FWT(A1),FWT(A0)−FWT(A1))