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))
也许更好的阅读体验 本文主要内容是对武汉市第二中学吕凯风同学的论文<集合幂级数的性质与应用及其快速算法>的理解 定义 集合幂级数 为了更方便的研究集合的卷积,引入集合幂级数的概念 集合幂级 ...
随机推荐
- Maven 依赖管理问题小计
刚学Maven,遇到点小问题,记录一下.https://maven.apache.org/ 问题的起因是项目中使用了 Hibernate Validator ,但是运行起来后总是不能按照设置的注解校验 ...
- Lucene7.4学习和简单使用
简述: 前面从新回顾学习了Solr,正好也借此机会顺便学习一下Lucene. 一.什么是Lucene? 全文检索的一个实现方式,也是非结构化数据查询的方法.应用场景:在数据量大,数据结构不固定的时候, ...
- [原创]SSH 隧道转发
目录 简介 本地SSH隧道 远程SSH隧道 FAQ 免密码登陆 自动重连 简介 建立ssh隧道常用于, 通过一台公网的主机或者是大家都可以访问的主机做跳转机,来访问内部或者外部不能直接访问的机器. 项 ...
- 逆向学习-Windows消息钩取
钩子 Hook,就是钩子.偷看或截取信息时所用的手段或工具. 消息钩子 常规Windows流: 1.发生键盘输入事件时,WM_KEYDOWN消息被添加到[OS message queue]. 2.OS ...
- remote link Centos6.6 Horrible Slow
客户端win7 , 本地直连,secureCRT连接Centos6.6 速度巨慢,FTP tool almost cannot link in. 即使用cmd ftp 也是反应30s以上.
- MySQL的库、表详细操作
本节目录 一.库操作 二.表操作 三.行操作 一.库操作 1.创建数据库 1.1 语法 CREATE DATABASE 数据库名 charset utf8; 1.2 数据库命名规则 可以由字母.数字. ...
- 20190417 CentOS 7下安装ActiveMQ
前言 用VMware安装CentOS 7.6,创建一个新的用户lihailin9073,并使用这个用户登陆CentOS系统 安装和启动 登陆ActivieMQ官网http://activemq.apa ...
- 20190415 OSX系统安装和配置maven
1.下载maven包[apache-maven-3.6.0-bin.zip] 2.解压到准备安装的目录,我的在:/Users/apple/Documents/javasource/apache-mav ...
- 发布aar到jcenter
准备工作 创建bintray账号; 在https://bintray.com/, 选择如下图中,方框内"Sign Up Here": 选择合适的方式,创建账号: 新建仓库: Add ...
- python-Event事件线程同步和互斥
#!/usr/bin/python #coding=utf-8 #用于线程间通信,通过事件标识控制 import threading from time import sleep,ctime def ...