快速沃爾什變換(FWT)

最近學了 min-max 容斥,好像幾乎每一道 min-max 容斥題都要用到 FWT 來輔助,所以順便學一下 FWT。

概述

與 FFT 類似。

需要求的是

C(k)=ij=kA(i)B(j)C(k)=\sum_{i\oplus j=k}A(i)*B(j)

其中 \oplus 可以指代位運算符號,例如按位和,按位或,按位異或。

實際上方法也非常類似。我們需要這樣一個變換和他的逆變換

FWT(AB)=FWT(A)FWT(B)FWT(A\oplus B)=FWT(A)\cdot FWT(B)

IFWT(FWT(A))=AIFWT(FWT(A))=A

其中 ABA \cdot B 表示多項式對應位置係數相乘。這樣子我們就可以先求得變換後的多項式,然後 O(n)O(n) 對應位置相乘,再變換回去。(廢話)

或卷積

FWT(A)i=ij=iAjFWT(A)_i=\sum_{i|j=i}A_j

感性理解就是算這個集合的所有子集的權值和。

可以發現

FWT(AB)=FWT(A)FWT(B)FWT(A|B)=FWT(A)\cdot FWT(B)

滿足要求。

然後我們看如何快速計算這個東西。

還是受 FFT 的啓發,考慮分治算這個東西。假設當前多項式 AA 次數爲 2n12^n-1 次,那麼我們把他按最高位是 00 還是 11 分成兩個次數爲 2n112^{n-1}-1 的多項式,叫做 A0,A1A0,A1

然後觀察可得

FWT(A)=(FWT(A0),FWT(A0)+FWT(A1))FWT(A)=(FWT(A0), FWT(A0)+FWT(A1))

其中 (A,B)(A,B) 表示兩個多項式首尾相接。原因很簡單,因爲要取子集,所以這一位爲 00 的一定包含於這一位爲 11 的集合中。

然後就可以分治 O(nlogn)O(n\log n) 算了呀。

他的逆變換是這樣的

IFWT(A)=(IFWT(A0),IFWT(A1)IFWT(A0))IFWT(A)=(IFWT(A0),IFWT(A1)-IFWT(A0))

感性理解起來也很方便,現在一個位置的數表示子集權值和,那我們還是一位一位考慮,把他的真子集全部都刪掉就好了。

具體證明就不證了。並且這個東西比 FFT 還好寫。

和卷積

一模一樣。您可以將公式替換到上面的或卷積中,然後復讀一遍。

FWT(A)i=i&j=iAjFWT(A)_i=\sum_{i\&j=i} A_j

表示取所有包含他的集合的權值和。

所以

FWT(A)=(FWT(A0)+FWT(A1),FWT(A1))FWT(A)=(FWT(A0)+FWT(A1), FWT(A1))

IFWT(A)=(FWT(A0)FWT(A1),FWT(A1))IFWT(A)=(FWT(A0)-FWT(A1), FWT(A1))

異或卷積

與上述兩個不是很一樣。稍微麻煩一點。這裏我們用更爲普適的方法來解決異或卷積的問題。

可以參考 這篇博客

異或卷積定義如下

(A  xor  B)i=j  xor  k=iAjBk(A\;xor\;B)_i=\sum_{j\;xor\;k=i}A_jB_k

首先我們假設異或變換爲

FWT(A)i=j=0n1K(i,j)AjFWT(A)_i=\sum_{j=0}^{n-1}K(i,j)A_j

其中 K(i,j)K(i,j) 爲關於 i,ji,j 的函數。

然後考慮到

FWT(A  xor  B)=FWT(A)FWT(B)FWT(A \; xor \; B)=FWT(A)\cdot FWT(B)

所以對於每一位 xx 都有

i=0n1K(x,i)(A  xor  B)i=j=0n1K(x,j)Ajk=0n1K(x,k)Bk\sum_{i=0}^{n-1}K(x,i)(A \; xor \; B)_i=\sum_{j=0}^{n-1}K(x,j)A_j\cdot \sum_{k=0}^{n-1}K(x,k)B_k

將最上面的定義帶代入,得到

i=0n1K(x,i)j  xor  k=iAjBk=j=0n1K(x,j)Ajk=0n1K(x,k)Bk\sum_{i=0}^{n-1}K(x,i)\sum_{j\;xor\;k=i}A_jB_k=\sum_{j=0}^{n-1}K(x,j)A_j\cdot \sum_{k=0}^{n-1}K(x,k)B_k

化簡

j=0n1k=0n1K(x,j  xor  k)AjBk=j=0n1k=0n1K(x,j)K(x,k)AjBk\sum_{j=0}^{n-1}\sum_{k=0}^{n-1}K(x,j\;xor\;k)A_jB_k=\sum_{j=0}^{n-1}\sum_{k=0}^{n-1}K(x,j)K(x,k)A_jB_k

所以我們發現

K(x,j  xor  k)=K(x,j)K(x,k)K(x,j\;xor\;k)=K(x,j)K(x,k)

只要係數滿足這個就完全可以做 FWT 了。但是因爲 IFWT 的需要,我們還要保證他可以反演,也就是說轉移矩陣可逆。

所以對於異或卷積,根據人類智慧,我們發現係數可以這樣設

K(x,i)=(1)x&iK(x,i)=(-1)^{|x\& i|}

其中 A|A| 表示集合大小,或者說一個二進制數中 11 的個數。

因爲考慮異或對集合大小奇偶性的影響,發現兩個集合異或之後他們集合大小的奇偶性也會異或起來。感性理解的話就把異或看成不進位的二進制加法就好。

然後因爲

(x&i)  xor  (x&j)=x&(i  xor  j)(x\&i)\;xor\;(x\& j)=x\&(i\;xor\;j)

上面的式子對於集合大小的奇偶性也是一樣的,所以係數

(1)x&(i  xor  j)=(1)x&i(1)x&j(-1)^{|x\&(i\;xor\;j)|}=(-1)^{|x\& i|}\cdot (-1)^{|x\& j|}

現在我們看看如何用分治來做異或卷積。

既然已經定義了

FWT(A)i=j=0n1(1)i&jAjFWT(A)_i=\sum_{j=0}^{n-1}(-1)^{|i\&j|}A_j

只要嘗試着在已知 FWT(A0),FWT(A1)FWT(A0),FWT(A1) 的情況下在每一個數前面加上 00 或者 11 再算一遍就好了,我們可以得到如下式子

FWT(A)=(FWT(A0)+FWT(A1),FWT(A0)FWT(A1))FWT(A)=(FWT(A0)+FWT(A1),FWT(A0)-FWT(A1))

IFWT(A)=(IFWT(A0)+IFWT(A1)2,IFWT(A0)IFWT(A1)2)IFWT(A)=(\frac{IFWT(A0)+IFWT(A1)}{2},\frac{IFWT(A0)-IFWT(A1)}{2})

大功告成。

總結

和 FFT 非常類似,可以類比 FFT 理解。

作爲一種工具,要熟練掌握並能在該用的地方用出來。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章