快速沃尔什变化 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)\)

可以证明是对的:

\[FWT(C_0)=C_0+C_1=A_0*B_0+A_1*B_1+A_1*B_0+A_0*B_1=(A_0+A_1)*(B_0+B_1) \]

\[FWT(C_0)=C_0-C_1=A_0*B_0+A_1*B_1-A_1*B_0-A_0*B_1=(A_0-A_1)*(B_0-B_1) \]

\[IFWT(C_0)=(FWT(C_0)+FWT(C_1))/2=[(A_0+A_1)*(B_0+B_1)+(A_0-A_1)*(B_0-B_1)]/2=A_0*B_0+A_1*B_1 \]

\[IFWT(C_1)=(FWT(C_0)-FWT(C_1))/2=[(A_0+A_1)*(B_0+B_1)-(A_0-A_1)*(B_0-B_1)]/2=A_0*B_1+A_0*B_1 \]

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;
			}
}
posted @ 2026-10-30 14:52  Rainesxiao  阅读(5)  评论(0)    收藏  举报