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))
也许更好的阅读体验 本文主要内容是对武汉市第二中学吕凯风同学的论文<集合幂级数的性质与应用及其快速算法>的理解 定义 集合幂级数 为了更方便的研究集合的卷积,引入集合幂级数的概念 集合幂级 ...
随机推荐
- CentOS7基础建站指南(笔记)
由于前段时间腾讯云打折,所以买了一台小服务器,想着以后写几个小网站,博客什么的,但是一开始就遇到了难题,大概就是Linux服务器的配置问题,比如如何假设服务器,配置非root用户,配置服务器数据的非r ...
- 前后端分离——token超时刷新策略
前言 记录一下前后端分离下————token超时刷新策略! 需求场景 昨天发了一篇记录 前后端分离应用——用户信息传递 中介绍了token认证机制,跟几位群友讨论了下,有些同学有这么一个疑惑:toke ...
- 架构师养成记--29.redis开篇
主要有从下几点讲解 NOSQL(Redis) 简介.redis安装与部署 Redis基础事件类型详解 Redis高级命令 Redis与java的使用 Redis集群搭建 Redis集群与spring的 ...
- 安装配置python、beautifulsoup4、pip的心酸总结
1.python下载安装不纠结,但如果要加入到eclipse里面就要注意一下版本,版本不匹配会造成,要不python降级,要不eclipse升级的情况 2.在稍新版本的python立面就附带下载在了p ...
- LOJ2229. 「BJOI2014」想法(随机化)
题目链接 https://loj.ac/problem/2229 题解 评分标准提示我们可以使用随机化算法. 首先,我们为每一道编号在 \([1, m]\) 以内的题目(这些题目也对应了 \(m\) ...
- RocketMQ之NameServer学习笔记
org.apache.rocketmq.namesrv.NamesrvController NameserController,NameServer的核心控制类. 1.1 NamesrvConfig ...
- [Xamarin.Android] 結合Windows Azure與Google cloud message 來實現Push Notification (转帖)
這一篇要討論如何使用Xamarin.Android 整合GCM以及Windows Azure來實作Android手機上的推播通知服務. 這篇文章比較著重概念的部分,在開始讀這篇之前,也可以先參考一下X ...
- (转)搞个这样的APP要多久?心酸啊。
这是一个“如有雷同,纯属巧合”的故事,外加一些废话,大家请勿对号入座.开始了…… 我有些尴尬地拿着水杯,正对面坐着来访的王总,他是在别处打拼的人,这几年据说收获颇丰,见移动互联网如火如荼,自然也想着要 ...
- 使用redux-devtools工具
在vue中型项目开发的过程中,一般都是要用到vuex这个状态管理工具的,这样可以方便我们管理全局的状态,同时,为了在开发的过程中,更加方便地实时查看到state状态,我们会使用 vue-devtool ...
- 高性能的数据压缩库libzling-20160105
libzling(https://github.com/richox/libzling,求观看[watch],求星[star],求叉[fork])是一款高性能的数据压缩库,参见原贴:http://ww ...