【理论】快速沃尔什变换(FWT)学习笔记
FWT 处理的是位运算卷积问题。
其解决的问题是对于长度为
其中
FWT 的思想是对数组
借此求得了
接下来我们来进行具体讲解:
首先,我们要将
我们考虑推
先利用性质
代入得对于任意
交换求和顺序:
我们得到了式
再将
将右式改为枚举
我们得到了式
式
据此,我们可以得到一个关于变换系数的一个重量级结论:
不难发现由于其性质,实际上我们可以按位考虑
通过按位考虑,我们原先要推出的变换系数
我们将变换系数求出来了,下一步呢?如何通过变换系数求出一个数组
我们仍然是考虑式子:
将其分为前后各大小为
考虑分为两部分的好处是什么,很显然对于前一部分
考虑将下标首位为
-
对于
, 。 -
对于
, 。
而 FWT 采用倍增的方法,这就导致了在计算长度为
那么 IFWT 呢?
观察到对于
那么不难发现 IFWT 只需要该矩阵求逆后再做一遍 FWT 即可。
同时这也对
我们回忆一下线性代数的知识,若二阶方阵的逆存在那么便等价于
好的那么 FWT 以及 IFWT 的过程就结束了,我们现在要对
(另外一个利用的性质是
显然
同时有
因为矩阵对角线乘积不等,所以
不妨令
我们得到矩阵为:
其逆矩阵为:
观察到此时
(逆矩阵可手动高斯消元得到,详见【模板】矩阵求逆 )
和
显然
同时有
因为矩阵对角线乘积不等,所以
不妨令
我们得到矩阵为:
其逆矩阵为:
观察到此时
首先
同时,对于任意
即
因为矩阵对角线乘积不等,所以
不妨令
我们得到矩阵为:
其逆矩阵为:
观察到此时
代码
void FWT(ll *f){
for(int len=1;len<=(1<<(n-1));len<<=1){
for(int i=0;i<(1<<n);i+=(len<<1)){
rep(j,i,i+len-1){
ll tmp=f[j];
f[j]=c[0][0]*f[j]+c[0][1]*f[j+len];
f[j+len]=c[1][0]*tmp+c[1][1]*f[j+len];
f[j]%=mod;
f[j+len]%=mod;
}
}
}
return;
}
void calc(ll tp){
rep(i,0,(1<<n)-1){
a[i]=A[i];
b[i]=B[i];
}
if(tp==1){
c[0][0]=c[1][1]=c[1][0]=1;
c[0][1]=0;
}
if(tp==2){
c[0][0]=c[0][1]=c[1][1]=1;
c[1][0]=0;
}
if(tp==3){
c[0][0]=c[0][1]=c[1][0]=1;
c[1][1]=-1;
}
FWT(a);
FWT(b);
rep(i,0,(1<<n)-1) C[i]=a[i]*b[i]%mod;
if(tp==1){
c[0][0]=c[1][1]=1;
c[0][1]=0;
c[1][0]=-1;
}
if(tp==2){
c[0][0]=c[1][1]=1;
c[0][1]=-1;
c[1][0]=0;
}
if(tp==3){
c[0][0]=c[0][1]=c[1][0]=inv(2);
c[1][1]=-c[0][0];
}
FWT(C);
rep(i,0,(1<<n)-1) C[i]=(C[i]+mod)%mod;
}
FWT 的性质:
FWT 是一种线性变换,所以其满足性质
由此可得,数乘其同样满足
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App