模板:快速莫比乌斯变换(FMT)+快速沃尔什变换(FWT)(多项式)
文章目錄
- 前言
- 解析
- OR
- 定義
- 變換:
- 逆變換
- 代碼
- AND
- 代碼
- XOR
- 定義
- 變換
- 逆變換
- 代碼
所謂快速沃爾什變換,就是快速的沃爾瑪什錦專柜變換
(逃)
前言
正常卷積的定義:ck=∑i+j=kaibjc_k=\sum_{i+j=k}a_ib_jck?=∑i+j=k?ai?bj?。
可以用FFT或者NTT在 O(nlog?n)O(n\log n)O(nlogn) 的復雜度內解決。
然而,有些時候,我們計算卷積的時候下標關系并不是喜聞樂見的加法,而是形如 ck=∑i⊕j=kaibjc_k=\sum_{i\oplus j=k}a_ib_jck?=∑i⊕j=k?ai?bj?,其中的 ⊕\oplus⊕ 是 and or xor 中的一種位運算。
這個時候就需要快速莫比烏斯變換(and or)和快速沃爾什變換(xor),同樣可以把復雜度降到 O(nlog?n)O(n\log n)O(nlogn) 級別。
解析
由于三個運算思想比較類似,因此不對兩個算法進行特別的區分,統稱為FWT。
采用類比的思想,FFT先把多項式轉化為點值表示,乘到一起,最后再反演回去。
類似的,FWT也是先把多項式 A,BA,BA,B 轉化為某種變換 FWT?(A),FWT?(B)\operatorname{FWT}(A),\operatorname{FWT}(B)FWT(A),FWT(B),然后乘起來得到 FWT?(C)\operatorname{FWT}(C)FWT(C),最后再反演回去得到 CCC。
根據不同位運算的性質,對應的變換有所不同。
OR
定義
求:ck=∑i∣?j=kaibjc_k=\sum_{i\operatorname{|}j=k}a_ib_jck?=∑i∣j=k?ai?bj?
考慮或運算有如下性質:若 i∣k=k,j∣k=ki|k=k,j|k=ki∣k=k,j∣k=k,那么 (i∣j)∣k=k(i|j)|k=k(i∣j)∣k=k,反之亦然。
那么我們就按照這個充要條件設計變換:FWT?or(A)k=∑i∣k=kAi\operatorname{FWT}_{or}(A)_k=\sum_{i|k=k}A_iFWTor?(A)k?=∑i∣k=k?Ai?。
自然語言:iii 必須是 kkk 的子集才能轉移。
考慮兩個變換后的多項式逐項系數相乘:
FWT?or(A)?FWT?or(B)=∑k(∑i∣k=kai)×(∑j∣k=kbj)\operatorname{FWT}_{or}(A)*\operatorname{FWT}_{or}(B)=\sum_{k}(\sum_{i|k=k}a_i)\times (\sum_{j|k=k}b_j)FWTor?(A)?FWTor?(B)=k∑?(i∣k=k∑?ai?)×(j∣k=k∑?bj?)
=∑k∑i∣k=k∑j∣k=kaibj=∑k∑(i∣j)∣k=kaibj=FWT?or(C)=\sum_{k}\sum_{i|k=k}\sum_{j|k=k}a_ib_j=\sum_{k}\sum_{(i|j)|k=k}a_ib_j=\operatorname{FWT}_{or}(C)=k∑?i∣k=k∑?j∣k=k∑?ai?bj?=k∑?(i∣j)∣k=k∑?ai?bj?=FWTor?(C)
所以我們就證出了系數直接相乘是對的,現在只需要一種快速的變換得到 FWT?or\operatorname{FWT}_{or}FWTor? 以及將其反演的方法。
變換:
還是和FFT類似的,考慮分治,假設我們要合并兩個長度為 2n2^n2n 的序列,設它們不同的最高位為1的序列為 A1A_1A1?,為0的為 A0A_0A0?。
考慮 or的性質,A0A_0A0? 可以轉移到 A1A_1A1?,而 A1A_1A1? 無法轉移到 A0A_0A0?,因此有:
FWT?or(A)=(FWT?or(A0),FWT?or(A0)+FWT?or(A1))\operatorname{FWT}_{or}(A)=(\operatorname{FWT}_{or}(A_0),\operatorname{FWT}_{or}(A_0)+\operatorname{FWT}_{or}(A_1))FWTor?(A)=(FWTor?(A0?),FWTor?(A0?)+FWTor?(A1?))
其中 +++ 表示系數逐項相加,(f(x),g(x))(f(x),g(x))(f(x),g(x)) 表示把 f(x)f(x)f(x) 和 g(x)g(x)g(x) 順次寫出。
逆變換
那么對應的,還原成原序列只需要逆向操作即可:
UFWT?or(A)=(UFWT?or(A0),UFWT?or(A0)?UFWT?or(A1))\operatorname{UFWT}_{or}(A)=(\operatorname{UFWT}_{or}(A_0),\operatorname{UFWT}_{or}(A_0)-\operatorname{UFWT}_{or}(A_1))UFWTor?(A)=(UFWTor?(A0?),UFWTor?(A0?)?UFWTor?(A1?))
代碼
寫起來非常簡潔:
void Or(ll *x,int n,int op){for(int l=1;l<n;l<<=1){for(int st=0;st<n;st+=l*2){for(int i=0;i<l;i++){ll u=x[st+i],v=x[st+l+i];if(op==1) x[st+i]=u,x[st+l+i]=(v+u)%mod;else x[st+i]=u,x[st+l+i]=(v+mod-u)%mod;}}} }AND
和 or 的整個定義、證明幾乎都是一樣的。
求:ck=∑i&?j=kaibjc_k=\sum_{i\operatorname{\&}j=k}a_ib_jck?=∑i&j=k?ai?bj?
與運算有如下性質:若 i&k=k,j&k=ki\&k=k,j\&k=ki&k=k,j&k=k,那么 (i&j)&k=k(i\&j)\&k=k(i&j)&k=k,反之亦然。
按照這個充要條件設計變換:FWT?or(A)k=∑i∣k=kAi\operatorname{FWT}_{or}(A)_k=\sum_{i|k=k}A_iFWTor?(A)k?=∑i∣k=k?Ai?。
自然語言:iii 必須是 kkk 的超集才能轉移。
后面的證明一模一樣,變換也可以同理的得到:
FWT?and(A)=(FWT?and(A0)+FWT?and(A1),FWT?and(A1))\operatorname{FWT}_{and}(A)=(\operatorname{FWT}_{and}(A_0)+\operatorname{FWT}_{and}(A_1),\operatorname{FWT}_{and}(A_1))FWTand?(A)=(FWTand?(A0?)+FWTand?(A1?),FWTand?(A1?))
UFWT?and(A)=(UFWT?and(A0)?UFWT?and(A1),UFWT?and(A1))\operatorname{UFWT}_{and}(A)=(\operatorname{UFWT}_{and}(A_0)-\operatorname{UFWT}_{and}(A_1),\operatorname{UFWT}_{and}(A_1))UFWTand?(A)=(UFWTand?(A0?)?UFWTand?(A1?),UFWTand?(A1?))
代碼
void And(ll *x,int n,int op){for(int l=1;l<n;l<<=1){for(int st=0;st<n;st+=l*2){for(int i=0;i<l;i++){ll u=x[st+i],v=x[st+l+i];if(op==1) x[st+i]=(u+v)%mod,x[st+l+i]=v;else x[st+i]=(u+mod-v)%mod,x[st+l+i]=v;}}} }XOR
這個和之前的有所不同。
定義
求:ck=∑i⊕?j=kaibjc_k=\sum_{i\operatorname{\oplus}j=k}a_ib_jck?=∑i⊕j=k?ai?bj?
設 d(x)d(x)d(x) 為二進制下 xxx 的1的個數的奇偶性(模2的結果)。
有性質:d(i&k)⊕d(j&k)=d((i⊕j)&k)d(i\& k)\oplus d(j\& k)=d((i\oplus j)\& k)d(i&k)⊕d(j&k)=d((i⊕j)&k)。
證明:
由于與運算,只考慮 kkk 為1的那些位。如果某一位 i,ji,ji,j 都是1或0,那么等號兩邊的奇偶性都不改變;如果某一位 i,ji,ji,j 一個是1一個是0,那么等號兩邊的奇偶性都改變;所以等號兩遍的奇偶性始終同步改變,最后就一定是相等的。
設計:
FWT?xor(A)k=∑i(?1)d(i&k)ai\operatorname{FWT}_{xor}(A)_k=\sum_{i} (-1)^{d(i\& k)}a_iFWTxor?(A)k?=i∑?(?1)d(i&k)ai?
那么還是嘗試逐項相乘:
FWT?xor(A)?FWT?xor(B)=∑k(∑i(?1)d(i&k)ai)×(∑j(?1)d(j&k)bj)\operatorname{FWT}_{xor}(A)*\operatorname{FWT}_{xor}(B)=\sum_k(\sum_{i} (-1)^{d(i\& k)}a_i)\times (\sum_{j} (-1)^{d(j\& k)}b_j)FWTxor?(A)?FWTxor?(B)=k∑?(i∑?(?1)d(i&k)ai?)×(j∑?(?1)d(j&k)bj?)
=∑k∑i,j(?1)d(i&k)+d(j&k)aibj=∑k∑i,j(?1)d(i&k)⊕d(j&k)aibj=\sum_k\sum_{i,j} (-1)^{d(i\& k)+d(j\& k)}a_ib_j=\sum_k\sum_{i,j} (-1)^{d(i\& k)\oplus d(j\& k)}a_ib_j=k∑?i,j∑?(?1)d(i&k)+d(j&k)ai?bj?=k∑?i,j∑?(?1)d(i&k)⊕d(j&k)ai?bj?
=∑k∑i,j(?1)d((i⊕j)&k)aibj=FWT?xor(C)=\sum_k\sum_{i,j} (-1)^{d((i\oplus j)\& k)}a_ib_j=\operatorname{FWT}_{xor}(C)=k∑?i,j∑?(?1)d((i⊕j)&k)ai?bj?=FWTxor?(C)
得證。
變換
還是分治的思想,考慮到增加一位后,只有下標最高位帶1的數貢獻到了下標最高位帶1的位置時,最高位與運算結果為1,1的個數增加一個,奇偶性改變,所有的符號都變為相反。其它的轉移都不變。
也就是:
FWT?xor(A)=(FWT?xor(A0)+FWT?xor(A1),FWT?xor(A0)?FWT?xor(A1))\operatorname{FWT}_{xor}(A)=(\operatorname{FWT}_{xor}(A_0)+\operatorname{FWT}_{xor}(A_1),\operatorname{FWT}_{xor}(A_0)-\operatorname{FWT}_{xor}(A_1))FWTxor?(A)=(FWTxor?(A0?)+FWTxor?(A1?),FWTxor?(A0?)?FWTxor?(A1?))
逆變換
反過來即可。
FWT?xor(A)=(FWT?xor(A0)+FWT?xor(A1)2,FWT?xor(A0)?FWT?xor(A1)2)\operatorname{FWT}_{xor}(A)=(\frac{\operatorname{FWT}_{xor}(A_0)+\operatorname{FWT}_{xor}(A_1)}{2},\frac{\operatorname{FWT}_{xor}(A_0)-\operatorname{FWT}_{xor}(A_1)}{2})FWTxor?(A)=(2FWTxor?(A0?)+FWTxor?(A1?)?,2FWTxor?(A0?)?FWTxor?(A1?)?)
代碼
void Xor(ll *x,int n,int op){for(int l=1;l<n;l<<=1){for(int st=0;st<n;st+=l*2){for(int i=0;i<l;i++){ll u=x[st+i],v=x[st+l+i];if(op==1) x[st+i]=(u+v)%mod,x[st+l+i]=(u+mod-v)%mod;else x[st+i]=(u+v)%mod*499122177%mod,x[st+l+i]=(u+mod-v)%mod*499122177%mod;}}} }Thanks for reading!
總結
以上是生活随笔為你收集整理的模板:快速莫比乌斯变换(FMT)+快速沃尔什变换(FWT)(多项式)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 生旦净末丑的意思 生旦净末丑分别是怎么解
- 下一篇: 新飞度平台(飞度备案)