學習筆記 快速沃爾什變換 FWT

2022-09-22 01:00:14 字數 4947 閱讀 2273

目錄2. 按位與卷積

3. 按位異或卷積

4. 高維前/字尾和與各類卷積的聯絡

5. 題目小結

想要快速計算

\[c[k]=(a\textb)[k]=\sum_j=k}a_ib_j

\]我們可以利用 \(\mathtt\)

的思想:將係數多項式轉化成點值多項式,\(\mathcal o(n)\) 求得答案後將其還原成係數多項式。

假設 \(a,b\) 均為多項式,則 \(a+b,a-b,a\times b\) 都代表著對位運算

\(\mid,\&,\oplus\) 分別表示或、與、異或。且若無特殊說明,\(i\subseteq j\) 表示在二進位制意義下 \(i\) 是 \(j\) 的子集。

定義\[\mathtt(a)[i]=\sum_a_j\\

\mathtt(\mathtt(a))=a

\]所以有

\[\begin

\big[\mathtt(a)\times \mathtt(b)\big][i]&=\sum_a_b_\\

&=\sum_a_b_

\end

\]按照定義將上面那個柿子 \(\mathtt\) 一下就是 \(a|b\) 了。

對於乙個多項式 \(a\),不妨設其長度為 \(2^n\),令 \(a_0,a_1\) 分別為前 \(2^\) 項,後 \(2^\) 項(其實也可以理解為將下標以二進位制的最高位分組),有:

\[\mathtt(a)=

\begin

\big(\mathtt(a_0),\mathtt(a_0+a_1)\big) & & n>0\\

a && n=0

\end

\]這個遞迴式可以這樣理解:最終能貢獻到前 \(2^\) 項的項的最高位一定為零,此時 \(a_1\) 這一部分一定無用,所以由 \(\mathtt(a_0)\) 組成;貢獻到後 \(2^\) 項的項的最高位可以為 \(0/1\),所以相當於沒有限制,此時貢獻到哪一位只由二進位制的後 \(n-1\) 位決定,所以 \(a_0[i]\) 和 \(a_1[i]\) 是等價的,可以對位相加。

由上文的證明,我們也可以得到 \(\mathtt(a_0+a_1)=\mathtt(a_0)+\mathtt(a_1)\).

\[\mathtt(a)=

\begin

\big(\mathtt(a_0),\mathtt(a_1-a_0)\big) & & n>0\\

a && n=0

\end

\]\(n=0\) 的情況就不再贅述,對於 \(n>0\) 的情況,我們直接將 \(\mathtt(a)\) 代入柿子:

\[\begin

\mathtt\big(\mathtt(a)\big)&=\big(\mathtt(\mathtt(a_0)),\mathtt(\mathtt(a_0+a_1)-\mathtt(a_0))\big)\\

&=\big(a_0,\mathtt(\mathtt(a_0)+\mathtt(a_1)-\mathtt(a_0)) \big)\\

&=(a_0,a_1)

\end

\]void or(int *f,int opt=1) (a)[i]=\sum_a_j\\

\mathtt(\mathtt(a))=a

\]所以有

\[\begin

\big[\mathtt(a)\times \mathtt(b)\big][i]&=\sum_a_b_\\

&=\sum_a_b_

\end

\]按照定義將上面那個柿子 \(\mathtt\) 一下就是 \(a\&b\) 了(其實計算 \(\mathtt(a\&b)\) 應該會更好理解,你會發現 \(\mathtt(a\&b)[i]\) 就是列舉 \(i\) 的超集 \(j\),再列舉 \(j_1,j_2\) 使得 \(j_1\&j_2=j\))。

\[\mathtt(a)=

\begin

\big(\mathtt(a_0+a_1),\mathtt(a_1)\big) & & n>0\\

a && n=0

\end

\]理解方式同上,就不再闡述。

\[\mathtt(a)=

\begin

\big(\mathtt(a_0-a_1),\mathtt(a_1)\big) & & n>0\\

a && n=0

\end

\]證明方式同上,就不再闡述。

void and(int *f,int opt=1) (a)[i]=\sum_a_j-\sum_a_j=\sum (-1)^\cdot a_j\\

\mathtt(\mathtt(a))=a

\]在證明 \(\mathtt(a\oplus b)=\mathtt(a)\times \mathtt(b)\) 之前,首先有結論:\((i\circledast j)\oplus (i\circledast k)=i\circledast (j\oplus k)\).

具體證明可以對 \(i,j,k\) 二進位制的每一位考慮,如果每一位都成立那麼總結論也可以推知。只證明一位的話分類討論或者打表都行 /ww.

那麼\[\begin

\big[\mathtt(a)\times \mathtt(b)\big][i]&=\left(\sum_a_j-\sum_a_j \right)\cdot\left(\sum_b_k-\sum_b_k\right)\\

&=\sum_a_jb_k-\sum_a_jb_k=\mathtt(a\oplus b)[i]

\end

\]\[\mathtt(a)=

\begin

\big(\mathtt(a_0)+\mathtt(a_1),\mathtt(a_0)-\mathtt(a_1)\big) & & n>0\\

a && n=0

\end

\]證明就是暴力推柿子:

\[\begin

\mathtt(a)[i]&=\sum_^(-1)^a_j\\

&=\sum_^-1}(-1)^a_j+\sum_}^-1}(-1)^a_j\\

&=\mathtt(a_0)[i]+\sum_^-1}(-1)^a_}\\

&=\mathtt(a_0)[i]+\mathtt(a_1)[i]

\end

\]若 \(n>0\):

\[\mathtt(a)=\left(\frac(a_0)+\mathtt(a_1)},\frac(a_0)-\mathtt(a_1)}\right)

\]需要證明 \(\mathtt(a_0+a_1)=\mathtt(a_0)+\mathtt(a_1)\),這個由 \(\mathtt(a)[i]=\sum (-1)^\cdot a_j\) 可以輕鬆得出。

接下來就與1.3. 逆變換相同,直接代入即可。

void xor(int *f,int opt=1) \cdot \prod_^n [0\le j_\le p_k]

\]可以發現,所謂的 \(\mathtt(a)[i]\) 其實就是 \(s_i\). 那麼我們將 \(s_i\) 與 \(t_i\) 相乘,看看得到了什麼:

\[s_it_i=\sum a_\cdot b_\cdot \prod_^n [0\le j_\le p_l]\cdot [0\le k_\le p_l]

\]定義 \(f(i)=(\max(0,p_1-1)\max(0,p_2-1)\dots \max(0,p_n-1))_2\). 是的,你沒有看錯,這個玩意兒就是零,我也覺得好它嗎怪。那麼

\[s_it_i-s_t_=\sum a_\cdot b_\cdot \prod_^n [\max\=p_l]

\]怎麼說呢,這個柿子可以用多重for迴圈來理解。如果只考慮 \(1\) 維字首和(二進位制只有 \(1\) 位)就可以畫乙個矩形來表示 \(s_it_i\),那麼 \(s_it_i-s_t_=s_it_i-s_t_\),其實這個差可以看作旋轉 \(180^\circ\) 的l形圖案。

這個圖案就是我們要求的 \((a|b)[i]\) 了。所以說,高維字首和的差分就是 \(\mathtt\).

其實是一樣的,只不過是字首和變成了字尾和,\(\max\) 卷積變成了 \(\min\) 卷積。

我也只會口胡,你可以發現 \(\gcd\) 和 \(\text\) 卷積實際上是冪次上的 \(\min\) 和 \(\max\) 卷積。

例 1.\(\text\)

考慮到 \(n\) 是很小的,可以枚舉行的翻轉狀態,定義狀態 \(i\) 得到的最小 \(1\) 個數為 \(c_i\). 設 \(a_i\) 為列狀態為 \(i\) 的列數,\(b_i\) 為 \(i\) 和 \(2^n\oplus i\) 更少的 \(1\) 的個數(列舉列的翻轉)。那麼有:\(c_i=\sum a_jb_\). 這就是乙個很板的 \(\mathtt\) 了。但一定要注意資料範圍的計算

例 2.\(\text\)

令 \(p(x)=[x\text\wedge x\le m ]\),那麼答案顯然是 \(p^n[0]\),定義 "乘法" 為 \(\oplus\).

這道題目其實就是將 \(\mathtt(a\oplus b)=\mathtt(a)\times \mathtt(b)\) 拓展到

\[\mathtt(a_1\oplus a_2\oplus\dots \oplus a_n)=\mathtt(a_1)\times \mathtt(a_2)\times \dots\times \mathtt(a_n)

\]類似於 \(a\oplus b=\mathtt(\mathtt(a)\times \mathtt(b))\),再乘上 \(c\) 得:

\[\begin

(a\oplus b)\oplus c&=\mathtt(\mathtt(a\oplus b)\times \mathtt(c))\\

&=\mathtt(\mathtt(a)\times \mathtt(b)\times \mathtt(c))

\end

\]結論可以歸納證明。

學習筆記 FWT 快速沃爾什變換

解決涉及子集配湊的卷積問題 就是解決一類問題 f k sum a i b j 基本思想和fft類似。首先轉化成為另乙個多項式 fwt a fwt b 使得 fwt a oplus b fwt a fwt b 這裡,是按位乘。這個是 o n 的。然後,再 ifwt 回去即可。類似於,直接過馬路不好走。...

學習筆雞 快速沃爾什變換FWT

快速解決 c i sum a j b k fwt使得我們 fwt c fwt a fwt b 其中 是點積,就是對應位置乘起來。而對於 orfwt c i fwt c i sum c j 那麼證明一下 begin c i sum c j sum sum a p b k sum a p b k sum...

FFT 快速傅利葉變換 FWT 快速沃爾什變換

實在是 美麗的數學啊 關於傅利葉變換的部落格 講的很細緻 非常易於理解 大概能明白傅利葉變換是幹嗎的了 但是還是不能明白為什麼用傅利葉變換來算多項式求和 在多項式中,dft就是係數表式轉換成點值表示的過程。我們熟知的是多項式的係數表示法,通過給定一組 來確定乙個唯一的多項式 而多項式還可以有另一種表...