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))
也许更好的阅读体验 本文主要内容是对武汉市第二中学吕凯风同学的论文<集合幂级数的性质与应用及其快速算法>的理解 定义 集合幂级数 为了更方便的研究集合的卷积,引入集合幂级数的概念 集合幂级 ...
随机推荐
- php实现图片base64编码解码
1.图片的base64编码 /*首先要确定图片的类型,需要安装一个php拓展php_fileinfo 如已安装可以在extension_dir目录下找到php_fileinfo.dll(windows ...
- 【2】JMicro微服务-Hello World
如非授权,禁止用于商业用途,转载请注明出处作者:mynewworldyyl 1. 首先完成 JMicro微服务-RPC体验 的1到5步. 按默认方式启动ZK及Redis: JDK需要Java8及以上. ...
- 此博客不再维护,请移步http://daiweilai.github.io/
此博客不再维护,请移步新博客 http://daiweilai.github.io/ 新开的这个博客系统,托管在了Github.io上,喜闻乐见的Jekll加借鉴(抄袭)的精美主题构建而成,反正样子应 ...
- docker阿里云镜像加速器使用
加速器使用:加快镜像下载速度 访问www.aliyun.com: 登录之后点击”控制台“,选择“产品与服务“: 选择“容器镜像服务“: 设定密码后选择“镜像加速器”: 这里会有一个加速器地址: 在 ...
- [转] String to Date conversion in hive - 在 Hive 中各种字符串转换成日期格式
[From] http://bigdataprogrammers.com/string-date-conversion-hive/ Please refer below table to conver ...
- *args and **kwargs
首先要知道, 并不是必须写成*args 和**kwargs. 只有变量前面的 *(星号)才是必须的. 你也可以写成*var 和**vars. 而写成*args 和**kwargs只是一个通俗的命名约定 ...
- c# 获取项目根目录方法
编写程序的时候,经常需要用的项目根目录.自己总结如下 1.取得控制台应用程序的根目录方法 方法1.Environment.CurrentDirectory 取得或设置当前工作目录的完整限定路径 ...
- json对象和数组
Json数据就是格式化的字符串.c#中如果做为参数调用,类型就是string.1.Json数组 方括号[{ "firstName":"John" , " ...
- 一张图说清楚SQL的Join
话不多说..看图
- Mac 10.12安装图片标注工具PxCook
说明:现在基本是PxCook最好用,其余都是收费的,并且支持Android标注dp,主要是用于App开发时坐标定位,求到比例等等. 下载: (链接: https://pan.baidu.com/s/1 ...