快速沃尔什变换(FWT)

本文介绍了FWT(FastWalshTransform)在解决位运算卷积问题中的方法,通过分治策略将多项式分解并利用位运算特性快速计算,以O(n)的复杂度实现与、或、异或的卷积操作。

简介\huge 简介简介

FWTFWTFWT 是用于解决对下表进行位运算卷积问题的方法

更确切地说,给定两个多项式 AAABBB ,求多项式 CCC

ci=∑i=j⊕kajbkc_i = \sum _{i=j⊕k}a_jb_kci=i=jkajbk

其中, ⊕表示任意位运算符号(与(&),或(|),异或(^)之一)

FFTFFTFFT 类似,FWTFWTFWT 先将 A,BA,BA,B 转换成 FWTFWTFWT 的形式,相乘后再用逆变换转换成多项式形式。

以下会对三种位运算符号分别推导。



或\huge 或

要求

ci=∑i=j∥kajbkc_i = \sum _{i=j\|k}a_jb_kci=i=jkajbk

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=ji=iaj

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=ji=iajki=ibk                     

=∑j∣i=i∑k∣i=iajbk=\sum_{j|i=i} \sum_{k|i=i}a_jb_k=ji=iki=iajbk

=∑(j∣k)∣i=iajbk  =\sum_{(j|k)|i=i}a_jb_k\ \ =(jk)i=iajbk  

=FWT[c]i     =FWT[c]_i\ \ \ \ \ =FWT[c]i     

且就是说可以通过按位相乘的方式,以 O(n)O(n)O(n) 的复杂度解决两个 FWTFWTFWT 的卷积。

接下来要解决的是如何求一个多项式的 FWTFWTFWT

采用分治策略,每一次将多项式分为左半边 a0a_0a0 和右半边 a1a_1a1

其一定满足左半边下标最高位为 000 ,右半边下标最高位为 111

QQ截图20230504142542.png

如图所示,先分别计算两边的值,由于 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=iajbk

构造 FWT[a]_i=∑j&i=iajFWT[a]\_i = \sum _{j\&i=i} a_jFWT[a]_i=j&i=iaj

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=iaj(k&i=ibk)                       

=∑j&i=i∑k&i=iajbk=\sum_{j\&i=i} \sum_{k\&i=i}a_jb_k=j&i=ik&i=iajbk

=∑(j&k)&i=iajbk  =\sum_{(j\&k)\&i=i}a_jb_k\ \ =(j&k)&i=iajbk  

=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 2xy=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)(ij)xor(ik)=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=ij=0ajij=1aj

则有

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=(ij=0ajij=1aj)(ik=0bkik=1bk)          

=∑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)=0ajbki(j xor k)=1ajbk

=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;
			}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值