WIKIOI
wiki(I:)
比赛相关
工具软件
语言基础
算法基础
搜索
动态规划
字符串
数学
数据结构
图论
计算几何
杂项
专题
数学部分简介
符号
复数
位运算
快速幂
进位制
高精度计算
平衡三进制
素数
最大公约数
欧拉函数
筛法
欧拉定理 & 费马小定理
类欧几里德算法
裴蜀定理
乘法逆元
线性同余方程
中国剩余定理
二次剩余
BSGS
原根
卢卡斯定理
莫比乌斯反演
杜教筛
Min_25 筛
分解质因数
多项式部分简介
拉格朗日插值
快速傅里叶变换
快速数论变换
快速沃尔什变换
多项式求逆
多项式开方
多项式除法|取模
多项式对数函数|指数函数
多项式牛顿迭代
多项式多点求值|快速插值
多项式三角函数
多项式反三角函数
常系数齐次线性递推
生成函数简介
普通生成函数
指数生成函数
向量
矩阵
高斯消元
线性基
线性规划简介
单纯形算法
排列组合
卡特兰数
斯特林数
贝尔数
伯努利数
康托展开
容斥原理
抽屉原理
概率初步
置换群
斐波那契数列
博弈论
牛顿迭代法
数值积分
分段打表
64 objects
本站非官方,所收集资源均来源于网络。
快速沃尔什变换 - 数学
author: Xeonacid (本文转载自 [桃酱的算法笔记](https://zhuanlan.zhihu.com/c_1005817911142838272) ,原文戳 [链接](https://zhuanlan.zhihu.com/p/41867199) ,已获得作者授权) ## 简介 > 沃尔什转换(Walsh Transform)是在频谱分析上作为离散傅立叶变换的替代方案的一种方法。—— [维基百科](https://zh.wikipedia.org/zh-cn/%E6%B2%83%E7%88%BE%E4%BB%80%E8%BD%89%E6%8F%9B) 其实这个变换在信号处理中应用很广泛,fft 是 double 类型的,但是 walsh 把信号在不同震荡频率方波下拆解,因此所有的系数都是绝对值大小相同的整数,这使得不需要作浮点数的乘法运算,提高了运算速度。 所以,FWT 和 FFT 的核心思想应该是相同的,都是对数组的变换。我们记对数组 $A$ 进行快速沃尔什变换后得到的结果为 $FWT[A]$ 。 那么 FWT 核心思想就是: 我们需要一个新序列 $C$ ,由序列 $A$ 和序列 $B$ 经过某运算规则得到,即 $C = A \cdot B$ ; 我们先正向得到 $FWT[A], FWT[B]$ ,再根据 $FWT[C]=FWT[A] \cdot FWT[B]$ 在 $O(n)$ 的时间复杂度内求出 $FWT[C]$ ; 然后逆向运算得到原序列 $C$ 。时间复杂度为 $O(n \log{n})$ 。 在算法竞赛中,FWT 是用于解决对下标进行位运算卷积问题的方法。 公式: $C_{i} = \sum_{i=j \bigoplus k}A_{j} B_{k}$ (其中 $\bigoplus$ 是二元位运算中的某一种, $*$ 是普通乘法) ## FWT 的运算 ### FWT 之与(&)运算和或(|)运算 与运算和或运算的本质是差不多的,所以这里讲一下或运算,与运算也是可以自己根据公式 yy 出来的。 ### 或运算 如果有 $k=i|j$ ,那么 $i$ 的二进制位为 $1$ 的位置和 $j$ 的二进制位为 $1$ 的位置肯定是 $k$ 的二进制位为 $1$ 的位置的子集。 现在要得到 $FWT[C] = FWT[A] * FWT[B]$ ,我们就要构造这个 fwt 的规则。 我们按照定义,显然可以构造 $FWT[A] = A' = \sum_{i=i|j}A_{j}$ ,来表示 $j$ 满足二进制中 $1$ 为 $i$ 的子集。 那么显然会有 $C_{i} = \sum_{i=j|k}A_{j}*B_{k} \Rightarrow FWT[C] = FWT[A] * FWT[B]$ 那么我们接下来看 $FWT[A]$ 怎么求。 首先肯定不能枚举了,复杂度为 $O(n^2)$ 。既然不能整体枚举,我们就考虑分治。 我们把整个区间二分,其实二分区间之后,下标写成二进制形式是有规律可循的。 我们令 $A_0$ 表示 $A$ 的前一半, $A_1$ 表示区间的后一半,那么 $A_0$ 就是 A 下标最大值的最高位为 $0$ ,他的子集就是他本身的子集(因为最高位为 $0$ 了),但是 $A_1$ 的最高位是 $1$ ,他满足条件的子集不仅仅是他本身,还包最高位为 $0$ 的子集,即 $$ FWT[A] = merge(FWT[A_0], FWT[A_0] + FWT[A_1]) $$ 其中 merge 表示像字符串拼接一样把它们拼起来, $+$ 就是普通加法,表示对应二进制位相加。 这样我们就通过二分能在 $O(\log{n})$ 的时间复杂度内完成拼接,每次拼接的时候要完成一次运算,也就是说在 $O(n\log{n})$ 的时间复杂度得到了 $FWT[A]$ 。 接下来就是反演了,其实反演是很简单的,既然知道了 $A_0$ 的本身的子集是他自己 ( $A_0 = FAT[A_0]$ ), $A_1$ 的子集是 $FAT[A_0] + FAT[A_1](A_1'= A_0' + A_1'$ ),那就很简单的得出反演的递推式了: $$ UFWT[A'] = merge(UFWT[A_0'], UFWT[A_1'] - UFWT[A_0']) $$ ### 与运算 与运算类比或运算可以得到类似结论 $$ FWT[A] = merge(FWT[A_0] + FWT[A_1], FWT[A_1]) $$ $$ UFWT[A'] = merge(UFWT[A_0'] - UFWT[A_1'], UFWT[A_1']) $$ ### 异或运算 最常考的异或运算。 异或的卷积是基于如下原理: 若我们令 $i\And j$ 中 $1$ 数量的奇偶性为 $i$ 与 $j$ 的奇偶性,那么 $i$ 与 $k$ 的奇偶性异或 $j$ 和 $k$ 的奇偶性等于 $i \operatorname{xor} j$ 和 $k$ 的奇偶性。 对于 $FWT[A]$ 的运算其实也很好得到。 公式如下: $A_{i} = \sum_{C_1}A_{j} - \sum_{C_2}A_{j}$ ( $C_1$ 表示 $i \And j$ 奇偶性为 $0$ , $C_2$ 表示 $i \And j$ 的奇偶性为 $1$ ) 结论: $$ FWT[A] = merge(FWT[A_0] + FWT[A_1], FWT[A_0] - FWT[A_1]) $$ $$ UFWT[A'] = merge(\frac{FWT[A_0'] + FWT[A_1']}{2}, \frac{FWT[A_0'] - FWT[A_1']}{2}) $$ ### 同或运算 类比异或运算给出公式: $A_{i} = \sum_{C_1}A_{j} - \sum_{C_2}A_{j}$ ( $C_1$ 表示 $i|j$ 奇偶性为 $0$ , $C_2$ 表示 $i|j$ 的奇偶性为 $1$ ) $$ FWT[A] = merge(FWT[A_1] - FWT[A_0], FWT[A_1] + FWT[A_0]) $$ $$ UFWT[A'] = merge(\frac{FWT[A_1'] - FWT[A_0']}{2}, \frac{FWT[A_1'] + FWT[A_0']}{2}) $$