Fast Walsh-Hadamard Transform——快速沃尔什变换(二)
上次的博客有点模糊的说...我把思路和算法实现说一说吧...
思路
关于快速沃尔什变换,为了方便起见,我们采用线性变换(非线性变换不会搞)。
那么,就会有一个变化前各数值在变换后各处的系数,即前一篇博文中的$f(i,j)$,表示线性变换中第$i$项到第$j$项的系数。
即
$$DWT(A)_i = \sum_{j=0}^{n-1} A_j * f(i,j)$$
那么,我们既然要求$\oplus$卷积在变换后等价于乘积,就有
$$DWT(A)_i * DWT(B)_i = DWT(C)_i$$
其中$C$是$A,B$的$\oplus$卷积。
那么,将线性变换式及卷积定义代入,并令对应项系数相等,就可得到结论:
$$f(i, j) * f(i, k) = f(i, j \oplus k)$$
那么,通过构造合适的$f(i,j)$,就可得出变换。
$f$函数的构造
我们以异或为例(因为这时最麻烦的)。
既然是位运算,那么我们就从位运算入手。
考虑位运算,我们只需要考虑一位的情况,对于多位运算需要将每位的结果相乘(注意是相乘,这很重要!)。
通过定义,我们得到
$$f(i, 0) * f(i, j) = f(i, 0 \oplus j) = f(i, j)$$
$$f(i, 1) * f(i, 1) = f(i, 0)$$
又由于我们不能使所有系数都相同,那么只能取
$$\begin{cases}
f(i, 0) &= 1\\
f(0, j) &= 1\\
f(1, 1) &= -1
\end{cases}$$
那么此时
$$DWT(a_0, a_1) = (a_0 + a_1, a_0 - a_1)$$
可以验证其满足规则。
算法实现:
要实现$FWT$,我们仿照快速傅里叶变换,首先将$A$分成两半$A_0, A_1$(按二进制最高位,即直接取前一半和后一半)递归调用$FWT$,然后,
合并时,根据下面的式子($i_0,i_1$分别表示$i$的最高位和剩余位):
$$\begin{aligned}
DWT(A)_i &= \sum_{j=0}^{n-1} f(i, j)A_j\\
&= \sum_{j=0}^{n/2-1}f(i,j)A_j + \sum_{j=n/2}^{n-1}f(i,j)A_j\\
&= \sum_{j=0}^{n/2-1}f(i_0,j_0)f(i_1,j_1)A_j + \sum_{j=n/2}^{n-1}f(i_0,j_0)f(i_1,j_1)A_j\\
&= \sum_{j=0}^{n/2-1}f(i_0,0)f(i_1,j_1)A_j + \sum_{j=n/2}^{n-1}f(i_0,1)f(i_1,j_1)A_j\\
&= f(i_0, 0)\sum_{j=0}^{n/2-1}f(i_1,j_1)A_j + f(i_1)\sum_{j=n/2}^{n-1}f(i_0,1)f(i_1,j_1)A_j\\
&= f(i_0, 0)*DWT(A_0)_{i_1} + f(i_0, 1)*DWT(A_1)_{i_1}\end{aligned}$$
其中由第2行到第3行是因为我们对多位的$f$直接定义为各位的$f$相乘,即
$$f(i,j)=f(i_0,j_0)*f(i_1,j_1)$$
那么,算法实现就简单多了。
FWT(A, len)
1 divide A into (A0, A1)
2 FWT(A0, len/2)
3 FWT(A1, len/2)
4 for i=0 to len/2
5 A[i]=f00*A0[i]+f01*A1[i]
6 A[i+len/2]=f10*A0[i]+f11*A1[i]
关于逆变换嘛。。。你只需要告诉自己:我只是要处理刚被$FWT$变换过的数组,我只需要把它倒过来。
那么
IFWT(A, len)
1 divide A into (A0, A1)
2 for i=0 to len/2
3 solve the equation set, where the unknown numbers are A0[i] and A1[i]:
4 f00*A0[i]+f01*A1[i]=A[i]
5 f10*A0[i]+f11*A1[i]=A[i+len/2]
6 IFWT(A0, len/2)
7 IFWT(A1, len/2)
(当然解二元一次方程组只需要手算出来就好啦)
把三种运算(即与,或,异或)的f给出来:
$$\begin{array}{c|cccc}
Ops & f_{00} & f_{01} & f_{10} & f_{11} \\
\hline
And & 1 & 1 & 0 & 1 \\
Or & 1 & 0 & 1 & 1 \\
Xor & 1 & 1 & 1 & -1
\end{array}
$$
附三种运算变换代码:
void FWT_And(int *A, int len) {
if (len == ) return;
int len2 = len >> ;
FWT_And(A, len2);
FWT_And(A + len2, len2);
for (int i = ; i < len2; ++i)
A[i] += A[i + len2];
}
void IFWT_And(int *A, int len) {
if (len == ) return;
int len2 = len >> ;
for (int i = ; i < len2; ++i)
A[i] -= A[i + len2];
IFWT_And(A, len2);
IFWT_And(A + len2, len2);
} void FWT_Or(int *A, int len) {
if (len == ) return;
int len2 = len >> ;
FWT_Or(A, len2);
FWT_Or(A + len2, len2);
for (int i = ; i < len2; ++i)
A[i + len2] += A[i];
}
void IFWT_Or(int *A, int len) {
if (len == ) return;
int len2 = len >> ;
for (int i = ; i < len2; ++i)
A[i + len2] -= A[i];
IFWT_Or(A, len2);
IFWT_Or(A + len2, len2);
} void FWT_Xor(int *A, int len) {
if (len == ) return;
int len2 = len >> ;
FWT_Xor(A, len2);
FWT_Xor(A + len2, len2);
for (int i = ; i < len2; ++i) {
int x = A[i], y = A[i + len2];
A[i] = x + y;
A[i + len2] = x - y;
}
}
void IFWT_Xor(int *A, int len) {
if (len == ) return;
int len2 = len >> ;
for (int i = ; i < len2; ++i) {
int x = A[i], y = A[i + len2];
A[i] = (x + y) >> ;
A[i + len2] = (x - y) >> ;
}
IFWT_Xor(A, len2);
IFWT_Xor(A + len2, len2);
}
Fast Walsh-Hadamard Transform——快速沃尔什变换(二)的更多相关文章
- Fast Walsh–Hadamard transform
考虑变换 $$\hat{A_x} = \sum_{i\ or\ x = x}{ A_i }$$ 记 $S_{t}(A,x) = \sum_{c(i,t)\ or\ c(x,t)=c(x,t),\ i ...
- Fast Walsh-Hadamard Transform——快速沃尔什变换
模板题: 给定$n = 2^k$和两个序列$A_{0..n-1}$, $B_{0..n-1}$,求 $$C_i = \sum_{j \oplus k = i} A_j B_k$$ 其中$\oplus$ ...
- 关于快速沃尔什变换(FWT)的一点学习和思考
最近在学FWT,抽点时间出来把这个算法总结一下. 快速沃尔什变换(Fast Walsh-Hadamard Transform),简称FWT.是快速完成集合卷积运算的一种算法. 主要功能是求:,其中为集 ...
- 能轻松背板子的FWT(快速沃尔什变换)
FWT应用 我不知道\(FWT\)的严格定义 百度百科和维基都不知道给一坨什么****东西** FWT(Fast Walsh Fransform),中文名快速沃尔什变换 然后我也不知道\(FWT\)到 ...
- FWT快速沃尔什变换学习笔记
FWT快速沃尔什变换学习笔记 1.FWT用来干啥啊 回忆一下多项式的卷积\(C_k=\sum_{i+j=k}A_i*B_j\) 我们可以用\(FFT\)来做. 甚至在一些特殊情况下,我们\(C_k=\ ...
- [学习笔记]FWT——快速沃尔什变换
解决涉及子集配凑的卷积问题 一.介绍 1.基本用法 FWT快速沃尔什变换学习笔记 就是解决一类问题: $f[k]=\sum_{i\oplus j=k}a[i]*b[j]$ 基本思想和FFT类似. 首先 ...
- 一个数学不好的菜鸡的快速沃尔什变换(FWT)学习笔记
一个数学不好的菜鸡的快速沃尔什变换(FWT)学习笔记 曾经某个下午我以为我会了FWT,结果现在一丁点也想不起来了--看来"学"完新东西不经常做题不写博客,就白学了 = = 我没啥智 ...
- 快速沃尔什变换 FWT 学习笔记【多项式】
〇.前言 之前看到异或就担心是 FWT,然后才开始想别的. 这次学了 FWT 以后,以后判断应该就很快了吧? 参考资料 FWT 详解 知识点 by neither_nor 集训队论文 2015 集合幂 ...
- 集合并卷积的三种求法(分治乘法,快速莫比乌斯变换(FMT),快速沃尔什变换(FWT))
也许更好的阅读体验 本文主要内容是对武汉市第二中学吕凯风同学的论文<集合幂级数的性质与应用及其快速算法>的理解 定义 集合幂级数 为了更方便的研究集合的卷积,引入集合幂级数的概念 集合幂级 ...
随机推荐
- Swift 函数提前返回
简评:函数提前返回主要的好处是:将每个错误处理进行分离,审查代码时不需要考虑多种复杂异常,我们可以吧注意力集中在也业务逻辑中,调试代码时可以直接在异常中打断点. 提前返回 首先来看一下需要改进的代码示 ...
- QuantLib 金融计算——基本组件之 Date 类
目录 QuantLib 金融计算--基本组件之 Date 类 Date 对象的构造 一些常用的成员函数 一些常用的静态函数 为估值计算配置日期 如果未做特别说明,文中的程序都是 Python3 代码. ...
- HTML01--基础概述
HTML:Hyper Text Markup Language,超文本标记语言,不是编程语言,而是标记语言,使用一套标记标签来描述网页.通常来说,我们平时打开浏览器看到的网页由三部分组成,分别是HTM ...
- 并发编程>>概念准备(一)
工于其善,必先利器 1.并发和并行的区别 并行:同一时间点执行多个任务(CPU多核或多个CPU同时执行多个任务) 并发:同一时间段内行多个任务(单核同时执行多个任务) 2.同步和异步的区别 同步:执行 ...
- MarkDown添加图片的三种方式
插图最基础的格式就是: ![Alt text](图片链接 "optional title") Alt text:图片的Alt标签,用来描述图片的关键词,可以不写.最初的本意是当图片 ...
- 【运维】centos7+confluence5.6.6破解
一.安装mysql数据库 centos7自带mariadb数据库,因为无法下载完整安装包,最终选择将其完全卸载,然后全新安装mysql数据库 1.卸载mariadb rpm -qa | grep ma ...
- Mac下常用按键符号⌘(command)、⌥(option)、⇧(shift)、⇪(caps lock)、⌃(control)、↩(return)、⌅(enter)
常用符号如下: ⌘(command) ⌥(option) ⇧(shift) ⇪(caps lock) ⌃(control) ↩(return) ⌅(enter) 对应键盘的位置如下: 如果每次都不记得 ...
- redis 数据库迁移
老大让把 一台机器上 redis 中所有的数据,迁移到另一台机器上 查了一下可以拷贝 rdb 文件, 此方法只适用于迁移到一个新的库, 迁移到正在使用的库就不行了, 而且 rdb 里面是所有的 db, ...
- TortoiseGit学习系列之TortoiseGit基本操作拉取项目(图文详解)
前面博客 TortoiseGit学习系列之TortoiseGit基本操作克隆项目(图文详解) TortoiseGit学习系列之TortoiseGit基本操作修改提交项目(图文详解) TortoiseG ...
- Linux下设置Tomcat开机启动
1.进入/etc/rc.d/init.d,新建文件tomcat,并让它成为可执行文件 chmod 755 tomcat. #!/bin/bash # # /etc/rc.d/init.d/tomcat ...