简介 \huge 简介 简介
F W T FWT FWT 是用于解决对下表进行位运算卷积问题的方法
更确切地说,给定两个多项式 A A A 和 B B B ,求多项式 C C C
c i = ∑ i = j ⊕ k a j b k c_i = \sum _{i=j⊕k}a_jb_k ci=i=j⊕k∑ajbk
其中, ⊕表示任意位运算符号(与(&),或(|),异或(^)之一)
与 F F T FFT FFT 类似, F W T FWT FWT 先将 A , B A,B A,B 转换成 F W T FWT FWT 的形式,相乘后再用逆变换转换成多项式形式。
以下会对三种位运算符号分别推导。
或 \huge 或 或
要求
c i = ∑ i = j ∥ k a j b k c_i = \sum _{i=j\|k}a_jb_k ci=i=j∥k∑ajbk
若 F W T [ a ] i FWT[a]_i FWT[a]i 表示为 a a a 转成 F W T FWT FWT 形势下的第 i i i 位
构造 F W T [ a ] _ i = ∑ j ∥ i = i a j FWT[a]\_i = \sum_{j\|i=i}a_j FWT[a]_i=j∥i=i∑aj
则
F W T [ a ] _ i × F W T [ b ] _ i = ( ∑ j ∥ i = i a j ) ( ∑ k ∥ i = i b k ) 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 = i a j b k =\sum_{j|i=i} \sum_{k|i=i}a_jb_k =j∣i=i∑k∣i=i∑ajbk
= ∑ ( j ∣ k ) ∣ i = i a j b k =\sum_{(j|k)|i=i}a_jb_k\ \ =(j∣k)∣i=i∑ajbk
= F W T [ c ] i =FWT[c]_i\ \ \ \ \ =FWT[c]i
且就是说可以通过按位相乘的方式,以 O ( n ) O(n) O(n) 的复杂度解决两个 F W T FWT FWT 的卷积。
接下来要解决的是如何求一个多项式的 F W T FWT FWT 。
采用分治策略,每一次将多项式分为左半边 a 0 a_0 a0 和右半边 a 1 a_1 a1 。
其一定满足左半边下标最高位为 0 0 0 ,右半边下标最高位为 1 1 1 。
如图所示,先分别计算两边的值,由于 0 ∣ 1 = 1 0|1=1 0∣1=1 ,所以最终合并的结果为
F W T [ a ] = m e r g e ( F W T [ a 0 ] , F W T [ a 0 ] + F W T [ a 1 ] ) FWT[a] = merge(FWT[a_0],FWT[a_0]+FWT[a_1]) FWT[a]=merge(FWT[a0],FWT[a0]+FWT[a1])
其中 + + + 表示按位相加。
易得反演递推式:
U F W T [ a ] = m e r g e ( U F W T [ a 0 ] , U F W T [ a 1 ] − U F W T [ a 0 ] ) 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 与 与
要求
c i = ∑ j & k = i a j b k c_i = \sum_{j\&k=i} a_jb_k ci=j&k=i∑ajbk
构造 F W T [ a ] _ i = ∑ j & i = i a j FWT[a]\_i = \sum _{j\&i=i} a_j FWT[a]_i=j&i=i∑aj
则
F W T [ a ] _ i × F W T [ b ] _ i = ( ∑ j & i = i a j ) ( ∑ k & i = i b k ) 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 = i a j b k =\sum_{j\&i=i} \sum_{k\&i=i}a_jb_k =j&i=i∑k&i=i∑ajbk
= ∑ ( j & k ) & i = i a j b k =\sum_{(j\&k)\&i=i}a_jb_k\ \ =(j&k)&i=i∑ajbk
= F W T [ c ] i =FWT[c]_i\ \ \ \ \ \ \ \ =FWT[c]i
同上或的递推式,由于 0 & 1 = 0 0\&1=0 0&1=0 ,所以递推式为
F W T [ a ] = m e r g e ( F W T [ a 0 ] + F W T [ a 1 ] , F W T [ a 1 ] ) FWT[a] = merge(FWT[a_0]+FWT[a_1],FWT[a_1]) FWT[a]=merge(FWT[a0]+FWT[a1],FWT[a1])
U F W T [ a ] = m e r g e ( U F W T [ a 0 ] − U F W T [ a 1 ] , U F W T [ a 1 ] ) 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 = p o p c o u n t ( x & y ) m o d 2 x⊗y=popcount(x\&y) \bmod 2 x⊗y=popcount(x&y)mod2,其中 p o p c o u n t popcount popcount 表示二进制下 1 1 1 的个数
满足 ( 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)
构造 f w t [ a ] _ i = ∑ i ⊗ j = 0 a j − ∑ i ⊗ j = 1 a j fwt[a]\_i=\sum_{i⊗j=0}a_j-\sum_{i⊗j=1}a_j fwt[a]_i=i⊗j=0∑aj−i⊗j=1∑aj
则有
f w t [ a ] _ i × f w t [ b ] _ i = ( ∑ i ⊗ j = 0 a j − ∑ i ⊗ j = 1 a j ) ( ∑ i ⊗ k = 0 b k − ∑ i ⊗ k = 1 b k ) 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 ) = 0 a j b k − ∑ i ⊗ ( j xor k ) = 1 a j b k =\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
= f w t [ c ] i =fwt[c]_i\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ =fwt[c]i
根据定义得出
F W T [ a ] = m e r g e ( F W T [ a 0 ] + F W T [ a 1 ] , F W T [ a 0 ] − F W T [ a 1 ] ) 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])
U F W T [ a ] = m e r g e ( U F W T [ a 0 ] + U F W T [ a 1 ] 2 , U F W T [ a 0 ] − U F W T [ a 1 ] 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;
}
}