快速沃尔什变化 FWT
简介
沃尔什转换(Walsh Transform)是在频谱分析上作为离散傅立叶变换的替代方案的一种方法,在信号处理中应用很广泛.FFT 是 double 类型的,但是 Walsh 把信号在不同震荡频率方波下拆解,因此所有的系数都是绝对值大小相同的整数,这使得不需要作浮点数的乘法运算,提高了运算速度.
在算法竞赛中,FWT 是用于解决对下标进行位运算卷积问题的方法.
例题
P4717 【模板】快速莫比乌斯 / 沃尔什变换 (FMT / FWT)
也就是求或卷积,和卷积,和异或卷积
核心思路
求序列 \(C=\sum A\space \cdotp B\) 时,构造一种 \(FWT\) 使得 \(FWT(C)=FWT(A)\space \cdotp FWT(B)\)
那么就可以先正向求 \(FWT(A)\) 和 \(FWT(B)\),然后 \(O(n)\) 求 \(FWT(C)\)
然后再反向求 \(C=IFWT(FWT(C))\) 即可,总复杂度 \(O(nlog(n))\)
详解
或卷积
按照每一位进行分治,即 \(F \rarr (F_0,F_1)\)
可以发现 \(C_0=A_0*B_0\),\(C_1=A_0*B_0+A_0*B_1+A_1*B_0+A_1*B_1=(A_0+A_1)*(B_0+B_1)\)
那么可以构造 \(FWT(F_0,F_1)=(F_0,F_0+F_1)\),\(IFWT(F_0,F_1)=(F_0,F_1-F_0)\)
void OR(int f[],int p=1){
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++) f[i+j+k]=(f[i+j+k]+f[i+j]*p%mod)%mod;
}
代码将FWT和IFWT做了合并
和卷积
与或卷积类似
\(FWT(F_0,F_1)=(F_0+F_1,F_1)\),\(IFWT(F_0,F_1)=(F_0-F_1,F_1)\)
void AND(int f[],int p=1){
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++) f[i+j]=(f[i+j]+f[i+j+k]*p%mod)%mod;
}
异或卷积
同样分治
构造 \(FWT(F_0,F_1)=(F_0+F_1,F_0-F_1)\),\(IFWT(F_0,F_1)=((F_0+F_1)/2,(F_0-F_1)/2)\)
可以证明是对的:
void XOR(int f[],int p=1){
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++){
int x=f[i+j],y=f[i+j+k];
f[i+j]=(x+y)%mod*p%mod,f[i+j+k]=(x-y+mod)%mod*p%mod;
}
}

浙公网安备 33010602011771号