简介\huge 简介简介
FWTFWTFWT 是用于解决对下表进行位运算卷积问题的方法
更确切地说,给定两个多项式 AAA 和 BBB ,求多项式 CCC
ci=∑i=j⊕kajbkc_i = \sum _{i=j⊕k}a_jb_kci=i=j⊕k∑ajbk
其中, ⊕表示任意位运算符号(与(&),或(|),异或(^)之一)
与 FFTFFTFFT 类似,FWTFWTFWT 先将 A,BA,BA,B 转换成 FWTFWTFWT 的形式,相乘后再用逆变换转换成多项式形式。
以下会对三种位运算符号分别推导。
或\huge 或或
要求
ci=∑i=j∥kajbkc_i = \sum _{i=j\|k}a_jb_kci=i=j∥k∑ajbk
若 FWT[a]iFWT[a]_iFWT[a]i 表示为 aaa 转成 FWTFWTFWT 形势下的第 iii 位
构造 FWT[a]_i=∑j∥i=iajFWT[a]\_i = \sum_{j\|i=i}a_jFWT[a]_i=j∥i=i∑aj
则
FWT[a]_i×FWT[b]_i=(∑j∥i=iaj)(∑k∥i=ibk) FWT[a]\_i \times FWT[b]\_i = \left( \sum_{j\|i=i}a_j \right) \left( \sum_{k\|i=i}b_k\right)\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ FWT[a]_i×FWT[b]_i=j∥i=i∑ajk∥i=i∑bk
=∑j∣i=i∑k∣i=iajbk=\sum_{j|i=i} \sum_{k|i=i}a_jb_k=j∣i=i∑k∣i=i∑ajbk
=∑(j∣k)∣i=iajbk =\sum_{(j|k)|i=i}a_jb_k\ \ =(j∣k)∣i=i∑ajbk
=FWT[c]i =FWT[c]_i\ \ \ \ \ =FWT[c]i
且就是说可以通过按位相乘的方式,以 O(n)O(n)O(n) 的复杂度解决两个 FWTFWTFWT 的卷积。
接下来要解决的是如何求一个多项式的 FWTFWTFWT 。
采用分治策略,每一次将多项式分为左半边 a0a_0a0 和右半边 a1a_1a1 。
其一定满足左半边下标最高位为 000 ,右半边下标最高位为 111 。

如图所示,先分别计算两边的值,由于 0∣1=10|1=10∣1=1 ,所以最终合并的结果为
FWT[a]=merge(FWT[a0],FWT[a0]+FWT[a1])FWT[a] = merge(FWT[a_0],FWT[a_0]+FWT[a_1])FWT[a]=merge(FWT[a0],FWT[a0]+FWT[a1])
其中 +++ 表示按位相加。
易得反演递推式:
UFWT[a]=merge(UFWT[a0],UFWT[a1]−UFWT[a0])UFWT[a] = merge(UFWT[a_0],UFWT[a_1] - UFWT[a_0])UFWT[a]=merge(UFWT[a0],UFWT[a1]−UFWT[a0])
实现实现实现
void OR(int *a, int x) {
for (int o = 2, k = 1; o <= n; o <<= 1, k <<= 1)
for (int i = 0; i < n; i += o)
for (int j = 0; j < k; j ++ )
a[i + j + k] = a[i + j + k] + a[i + j] * x;
}
与\Huge 与与
要求
ci=∑j&k=iajbkc_i = \sum_{j\&k=i} a_jb_k ci=j&k=i∑ajbk
构造 FWT[a]_i=∑j&i=iajFWT[a]\_i = \sum _{j\&i=i} a_jFWT[a]_i=j&i=i∑aj
则
FWT[a]_i×FWT[b]_i=(∑j&i=iaj)(∑k&i=ibk) FWT[a]\_i \times FWT[b]\_i = \left( \sum_{j\&i=i}a_j \right) \left( \sum_{k\&i=i}b_k\right)\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ FWT[a]_i×FWT[b]_i=j&i=i∑aj(k&i=i∑bk)
=∑j&i=i∑k&i=iajbk=\sum_{j\&i=i} \sum_{k\&i=i}a_jb_k=j&i=i∑k&i=i∑ajbk
=∑(j&k)&i=iajbk =\sum_{(j\&k)\&i=i}a_jb_k\ \ =(j&k)&i=i∑ajbk
=FWT[c]i =FWT[c]_i\ \ \ \ \ \ \ \ =FWT[c]i
同上或的递推式,由于 0&1=00\&1=00&1=0 ,所以递推式为
FWT[a]=merge(FWT[a0]+FWT[a1],FWT[a1])FWT[a] = merge(FWT[a_0]+FWT[a_1],FWT[a_1])FWT[a]=merge(FWT[a0]+FWT[a1],FWT[a1])
UFWT[a]=merge(UFWT[a0]−UFWT[a1],UFWT[a1])UFWT[a] = merge(UFWT[a_0]-UFWT[a_1],UFWT[a_1])UFWT[a]=merge(UFWT[a0]−UFWT[a1],UFWT[a1])
实现实现实现
void AND(int *a, int x) {
for (int o = 2, k = 1; o <= n; o <<= 1, k <<= 1)
for (int i = 0; i < n; i += o)
for (int j = 0; j < k; j ++ )
a[i + j] = a[i + j] + a[i + j + k] * x;
}
异或\Huge 异或异或
定义 x⊗y=popcount(x&y) mod 2x⊗y=popcount(x\&y) \bmod 2x⊗y=popcount(x&y)mod2,其中 popcountpopcountpopcount 表示二进制下 111 的个数
满足 (i⊗j)xor(i⊗k)=i⊗(j xor k)(i⊗j) \textsf{xor} (i⊗k) = i⊗(j \ \textsf{xor} \ k)(i⊗j)xor(i⊗k)=i⊗(j xor k)
构造 fwt[a]_i=∑i⊗j=0aj−∑i⊗j=1ajfwt[a]\_i=\sum_{i⊗j=0}a_j-\sum_{i⊗j=1}a_jfwt[a]_i=i⊗j=0∑aj−i⊗j=1∑aj
则有
fwt[a]_i×fwt[b]_i=(∑i⊗j=0aj−∑i⊗j=1aj)(∑i⊗k=0bk−∑i⊗k=1bk) fwt[a]\_i \times fwt[b]\_i = \left( \sum_{i⊗j=0}a_j-\sum_{i⊗j=1}a_j \right) \left( \sum_{i⊗k=0}b_k-\sum_{i⊗k=1}b_k \right)\ \ \ \ \ \ \ \ \ \ fwt[a]_i×fwt[b]_i=(i⊗j=0∑aj−i⊗j=1∑aj)(i⊗k=0∑bk−i⊗k=1∑bk)
=∑i⊗(j xor k)=0ajbk−∑i⊗(j xor k)=1ajbk=\sum_{i⊗(j\ \textsf{xor}\ k)=0}a_jb_k - \sum_{i⊗(j\ \textsf{xor} \ k)=1}a_jb_k=i⊗(j xor k)=0∑ajbk−i⊗(j xor k)=1∑ajbk
=fwt[c]i =fwt[c]_i\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ =fwt[c]i
根据定义得出
FWT[a]=merge(FWT[a0]+FWT[a1],FWT[a0]−FWT[a1])FWT[a] = merge(FWT[a_0]+FWT[a_1],FWT[a_0]-FWT[a_1])FWT[a]=merge(FWT[a0]+FWT[a1],FWT[a0]−FWT[a1])
UFWT[a]=merge(UFWT[a0]+UFWT[a1]2,UFWT[a0]−UFWT[a1]2)UFWT[a] = merge(\frac{UFWT[a_0]+UFWT[a_1]}{2},\frac{UFWT[a_0]-UFWT[a_1]}{2})UFWT[a]=merge(2UFWT[a0]+UFWT[a1],2UFWT[a0]−UFWT[a1])
实现实现实现
void XOR(int *a, int x) {
for (int o = 2, k = 1; o <= n; o <<= 1, k <<= 1)
for (int i = 0; i < n; i += o)
for (int j = 0; j < k; j ++ ) {
a[i + j] = a[i + j] + a[i + j + k];
a[i + j + k] = a[i + j] - a[i + j + k] - a[i + j + k];
a[i + j] = a[i + j] * x, a[i + j + k] = a[i + j + k] * x;
}
}
本文介绍了FWT(FastWalshTransform)在解决位运算卷积问题中的方法,通过分治策略将多项式分解并利用位运算特性快速计算,以O(n)的复杂度实现与、或、异或的卷积操作。
5087

被折叠的 条评论
为什么被折叠?



