FWT學習筆記
快速沃爾什變換學習筆記
(如果寫錯了請糾正)(表達不到位請多多包涵)
\(or\)
令\(f[i][x]\)表示第\(i+1\)位到第\(n\)位相同,第\(1\)位到第\(i\)位是\(x\)的子集的\(a[y]\)的和
于是FMT后的數組就是 \(f[n][x]\)
考慮如何計算\(f[i][x]\)
如果\(x\)的第\(i\)位是\(0\),那么\(f[i][x]=f[i-1][x]\)
如果是\(1\),那么\(f[i][x]=f[i-1][x]+f[i-1][x-2^{i-1}]\)
用滾動數組優化可以做到空間復雜度\(O(n)\)
對于第\(i\)層來說,相當于把整個序列分成了\(2^{n-i}\)段
每一段中的第\(i+1\)位到第\(n\)位相同,且每段左半段第\(i\)位是\(0\),右半段第\(i\)位是\(1\),相當于左半段對右半段對應的位置產生了貢獻
代碼就很容易寫出來了(_)
FMT的逆變換
與正變換類似,\(f[i][x]\)表示第\(i+1\)位到第\(n\)位是\(x\)的子集,且第\(1\)位到第\(i\)位相等的\(a[y]\)的和
如果\(x\)的第\(i\)位是\(0\),那么\(f[i][x]=f[i-1][x]\)
如果是\(1\),那么\(f[i][x]=f[i-1][x]-f[i-1][x-2^{i-1}]\)
是不是很簡單(_)
\(and\)
與\(or\)的本質相同
\(xor\)
這個就比較難了
也叫集合的對稱差卷積
定義 \(h=f \cdot g\)
\(h_S= \sum_{L \subseteq 2^U}\sum_{R \subseteq 2^U}[L \oplus R=S]f_Lg_R\)
首先注意到對于集合 \(S\) 有
\(\frac{1}{2^n}\sum_{T \subseteq 2^U} (-1)^{|S \cap T|} = [ S= \varnothing ]\)
這樣
\(h_S= \sum_{L \subseteq 2^U}\sum_{R \subseteq 2^U}[L \oplus R \oplus S = \varnothing]f_L g_R\)
\(=\sum_{L \subseteq 2^U}\sum_{R \subseteq 2^U} \frac{1}{2^n} \sum_{T \subseteq 2^U}(-1)^{|T \cap (L \oplus R \oplus S)|}f_Lg_R\)
\(=\sum_{L \subseteq 2^U}\sum_{R \subseteq 2^U} \frac{1}{2^n} \sum_{T \subseteq 2^U}(-1)^{|T \cap L|}(-1)^{|T \cap R|}(-1)^{|T \cap S|}f_Lg_R\)
\(=\frac{1}{2^n}\sum_{T \subseteq 2^U} (-1)^{|T \cap S |} \left[ \sum_{L \subseteq 2^U} (-1)^{|T \cap L|}f_L \right] \left[ \sum_{R \subseteq 2^U} (-1)^{|T \cap R|}g_R \right]\)
如果我們做出如下定義
對于集合冪級數 \(f\) 我們定義他的快速沃爾什變換為 \(\hat f\)
\(\hat {f_S} = \sum_{T \subseteq 2^U} f_T(-1)^{|S \cap T|}\)
那么 \(\hat{f}\)的逆變換 \(f\)
\(f_S =\frac{1}{2^n} \sum_{T \subseteq 2^U} \hat{f_S} (-1)^{|S \cap T|}\)
那么我們就有
\(h_S=\frac{1}{2^n}\sum_{T \subseteq 2^U} \hat{f_T} \hat{g_T}\)
所以就有 \(\hat{f_S}\hat{g_S}=\hat{h_S}\)
這樣就會得到\(h_S=\frac{1}{2^n}\sum_{T \subseteq 2^U} \hat{h_S}\)
所以現在的問題是怎么求 \(f\) 以及 \(\hat{f}\)
同樣還是 DP
令\(f[i][x]\)表示第 \(i+1\) 到第 \(n\) 位相同,且對\((-1)\)的指數貢獻不考慮第 \(i+1\) 到第 \(n\) 的\((-1)^k \times a[y]\) 的和
對于第 \(i\) 層來說
如果第 \(i\) 位是 \(0\) , 那么 \(f[i][x]=f[i-1][x]+f[i-1][x+2^{i-1}]\)
如果第 \(i\) 位是 \(1\) , 那么 \(f[i][x]=f[i-1][x-2^{i-1}]-f[i-1][x]\)
對于第\(i\)層的每一段,令 \(t1=f[i-1][x],t2=f[i-1][x+2^{i-1}]\)
那么 \(f[i][x]=t1+t2\)
\(f[i][x+2^{i-1}]=t1-t2\)
對于逆變換則把它倒回去就可以了
\(f[i][x]\)表示 \(1\)到\(i\)位相等,對指數貢獻為 \((i+1)\)位到\(n\)位的\((-1)^k \times a[y]\)的和
如果第 \(i\) 位是 \(0\) , 那么 \(f[i][x]=\frac{f[i-1][x]+f[i-1][x+2^{i-1}]}{2}\)
如果第 \(i\) 位是 \(1\) , 那么 \(f[i][x]=\frac{f[i-1][x-2^{i-1}]-f[i-1][x]}{2}\)
代碼:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int mm=998244353;
const int maxn=1000000;
const int inv2=499122177;
int n;
long long A[maxn];
long long B[maxn];
long long C[maxn];
void FMTor(long long *arr,int n,int f){
for(int k=1;k<n;k<<=1){
int p=k+k;
for(int i=0;i<n;i+=p){
for(int j=0;j<k;++j){
if(f==1){
arr[i+j+k]=(arr[i+j+k]+arr[i+j])%mm;
}else{
arr[i+j+k]=(arr[i+j+k]-arr[i+j]+mm)%mm;
}
}
}
}
}
void FMTand(long long *arr,int n,int f){
for(int k=1;k<n;k<<=1){
int p=k+k;
for(int i=0;i<n;i+=p){
for(int j=0;j<k;++j){
if(f==1){
arr[i+j]=(arr[i+j]+arr[i+j+k])%mm;
}else{
arr[i+j]=(arr[i+j]-arr[i+j+k]+mm)%mm;
}
}
}
}
}
void FWTxor(long long *arr,int n,int f){
for(int k=1;k<n;k<<=1){
int p=k+k;
for(int i=0;i<n;i+=p){
for(int j=0;j<k;++j){
long long x=arr[i+j],y=arr[i+j+k];
if(f==1){
arr[i+j]=(x+y)%mm;
arr[i+j+k]=(x-y+mm)%mm;
}else{
arr[i+j]=(x+y)*inv2%mm;
arr[i+j+k]=(x-y+mm)*inv2%mm;
}
}
}
}
}
int main(){
scanf("%d",&n);
for(int i=0;i<(1<<n);++i)scanf("%lld",&A[i]);
for(int i=0;i<(1<<n);++i)scanf("%lld",&B[i]);
FMTor(A,1<<n,1);
FMTor(B,1<<n,1);
for(int i=0;i<(1<<n);++i)C[i]=A[i]*B[i]%mm;
FMTor(A,1<<n,-1);
FMTor(B,1<<n,-1);
FMTor(C,1<<n,-1);
for(int i=0;i<(1<<n);++i)printf("%lld ",C[i]);
printf("\n");
FMTand(A,1<<n,1);
FMTand(B,1<<n,1);
for(int i=0;i<(1<<n);++i)C[i]=A[i]*B[i]%mm;
FMTand(A,1<<n,-1);
FMTand(B,1<<n,-1);
FMTand(C,1<<n,-1);
for(int i=0;i<(1<<n);++i)printf("%lld ",C[i]);
printf("\n");
FWTxor(A,1<<n,1);
FWTxor(B,1<<n,1);
for(int i=0;i<(1<<n);++i)C[i]=A[i]*B[i]%mm;
FWTxor(A,1<<n,-1);
FWTxor(B,1<<n,-1);
FWTxor(C,1<<n,-1);
for(int i=0;i<(1<<n);++i)printf("%lld ",C[i]);
printf("\n");
return 0;
}

浙公網安備 33010602011771號