Fast Walsh Transform 学习笔记 | FWT

fast,walsh,transform,fwt · 浏览次数 : 0

小编点评

**Part 1. 核心概念** * **FWT (Fast Walsh Transform):**是一种快速计算矩阵乘法的算法,它可以用于计算矩阵乘积。 * **FWT 的基本思想:**它利用了矩阵的结构来计算矩阵乘积。对于一个矩阵,我们可以将它分解为多个子矩阵,并通过计算这些子矩阵的乘积来计算整个矩阵的乘积。 * **FWT 的时间复杂度:**时间复杂度为 O(n2^n),其中 n 是矩阵的维数。 **Part 2. 模板题核心代码** ```cpp void fwtOr(ll *a, int n, int type) { for (int i = 1; i < (1 << n); i++) { for (int j = 0; j < (1 << n); j += (i < 1); for (int k = 0; k < i; ++k) { (a[j + k + i] += type * a[j + k]) %= P; } } } ``` **Part 3. 代码说明** * `wtOr()` 函数用于计算矩阵乘积的 OR 操作。 * `wtAnd()` 函数用于计算矩阵乘积的 AND 操作。 * `wtXor()` 函数用于计算矩阵乘积的 XOR 操作。 **其他** * 以上代码的复杂度是 O(n2^n),其中 n 是矩阵的维数。 * 我们可以使用 FWT 来对矩阵进行快速乘法。 * 为了实现 FWT,我们需要对矩阵进行分解,这可能会有性能影响。 * FWT 是一个非常有效的算法,在许多算法中都有应用。

正文

本文中使用 \(\cap\) 表示按位与,用 \(\cup\) 表示按位或

Part 1. 与/或 卷积

First. 问题引入

给定长度为 \(2^n\) 的数列 \(A,B\),求 \(C_i = \sum_{j \cup k = i} A_j \times B_k\)

显然有 \(O(4^n)\) 的暴力

Second. 变换

这一部分可以参考 快速莫比乌斯变换中的 Zeta 变换 ,即定义 \(\hat A_i\) 为序列 \(A\)\(i\) 的子集和

Third. 快速变换

考虑分治

对于长度为 \(2^n\) 的待求解的 \(\hat A\),我们把它分成独立的两部分,即 \([0,2^{n-1})\)\([2^{n-1},2^n)\) 两个区间分别求解

然后考虑这两个区间之间的贡献,发现只有 \([0,2^{n-1})\)\([2^{n-1},2^n)\) 有贡献,于是对于 \(i \in [0,2^{n-1})\),将 \(\hat A_{i}\) 加到 \(\hat A_{i+2^{n-1}}\) 中即可

时间复杂度 \(O(n 2^n)\)

Fourth. 逆变换

我们只需要对照正变换中的操作步骤,一步一步撤销变换即可

即对于 \(i \in [0,2^{n-1})\),将 \(\hat A_{i+2^{n-1}}\) 减去 \(\hat A_{i}\) 的贡献,然后再递归地求解


当然还有另外的做法,即我们要将长度为 \(2^n\)\(\hat A_i\) 在全集为 \(2^n-1\) 的情况下(即不考虑目前的长度外的子集)只包括自己的 \(A_i\),那么我们递归地求解完左右两个区间后,肯定有 \(\forall i\in [0,2^{n-1}),\hat A_{i+2^{n-1}}=\hat A_i+A_{i+2^{n-1}}\),因此减去贡献即可

in brief,可以先递归再减贡献,这样逆变换与正变换只有一个 +/- 的变化

Fifth. 推广

对于 \(\cap\) 的情况,与 \(\cup\) 十分相似,请读者尽量自己构造变换,推一下式子,可以加深理解

如果没有思路,here

Part 2. 异或 卷积

First. 问题引入

给定长度为 \(2^n\) 的数列 \(A,B\),求 \(C_i = \sum_{j \oplus k = i} A_j \times B_k\)

Second. 原理

\(\operatorname{popcnt}(i)\) 表示 \(i\) 在二进制下 1 的个数,则有

\[\operatorname{popcnt}(i \cap k) + \operatorname{popcnt}(j \cap k) \equiv \operatorname{popcnt}((i\oplus j)\cap k) \pmod 2 \]

证明:显然 \(k\)\(0\) 的位上,\(i,j\) 的取值不影响结果,那么设 \(i'=i\cap k,j'=j\cap k\),那么问题转化为

\[\operatorname{popcnt}(i') + \operatorname{popcnt}(j') \equiv \operatorname{popcnt}(i'\oplus j') \pmod 2 \]

对于 \(i',j'\) 每一位分开讨论,原命题易证

即异或不会改变 \(1\) 的总数的奇偶性

Third. 变换

我们尝试构造一个变换

\[\hat A_i = \sum_j g(i,j) A_j \]

例如对于 \(\cup\) 卷积 ,\(g(i,j)=[i\cup j=i]\)

这个 \(g\) 函数满足以下性质:

\[\begin{align} & \because \hat C_i = \hat A_i \times \hat B_i \\ & \therefore \sum_{p} g(i,p)C_p = \sum_{j,k} g(i,j)\times g(i,k)\times A_j \times B_k \\ & \therefore \sum_{p} g(i,p) \sum_{j \oplus k = p} A_j \times B_k = \sum_{j,k} g(i,j)\times g(i,k)\times A_j \times B_k \\ & \therefore \sum_{j,k} g(i,j \oplus k) A_j \times B_k = \sum_{j,k} g(i,j)\times g(i,k)\times A_j \times B_k \end{align} \]

即我们要使得 \(g(i,j)\times g(i,k) = g(i,j \oplus k)\)

因为 \(\operatorname{popcnt}(i \cap k) + \operatorname{popcnt}(j \cap k) \equiv \operatorname{popcnt}((i\oplus j)\cap k) \pmod 2\),我们发现 \(g(i,j) = (-1)^{\operatorname{popcnt}(i \cap j)}\) 满足这个性质

\[\hat A_i = \sum_j (-1)^{\operatorname{popcnt}(i \cap j)} A_j \]

手动推一下式子:

\[\begin{align} \hat A_i \times \hat B_i & = \sum_j g(i,j)A_j \times \sum_k g(i,k) B_k\\ & = \sum_j (-1)^{\operatorname{popcnt}(i \cap j)} A_j \times \sum_k (-1)^{\operatorname{popcnt}(i \cap k)} B_k\\ & = \sum_{j,k} (-1)^{\operatorname{popcnt}(i \cap j) + \operatorname{popcnt}(i \cap k)} A_j \times B_k \\ & = \sum_{j,k} (-1)^{\operatorname{popcnt}(i \cap (j \oplus k))} C_{j \oplus k} \\ & = \sum_{p} (-1)^{\operatorname{popcnt}(i \cap p)} C_p \\ & = \sum_p g(i,p) C_p \\ & = \hat C_i \end{align} \]

Fourth. 快速变换

有点抽象,画个 \(n=3\) 的图来模拟一下

快速变换图解

假设现在我们要考虑从 \(n=2\)\(n=3\) 的变换,我们发现左边是 0??,右边是 1??,分别多出一个最高位

设原变换为 \(F_i\) ,目标变换为 \(G_i\)

  • \(\to\)

    我们发现左边内部之间的 \(\cup\) 结果不变,因此 \(\forall i<4, G_i \gets F_i\)

  • \(\to\) 右 / 右 \(\to\)

    我们发现 0?? \(\cup\) 1?? = 0??,因此其 1 的个数不变,因此 \(\forall i<4,G_i \gets F_{i+4}, G_{i+4} \gets F_i\)

  • \(\to\)

    我们发现之前是 ?? \(\cup\) ?? = ??,但是现在在前面加了一个 1,因此 \(-1\) 的指数加一,所以 \(\forall i<4,G_{i+4} \gets -F_{i+4}\)

综上,我们有 \(\forall i<4,G_i=F_i+F_{i+4}, G_{i+4}=F_i-F_{i+4}\)

generally,对于从 \(n-1\)\(n\) 的变换,我们有

\[\forall i<2^{n-1}, G_i=F_i+F_{i+2^{n-1}}, G_{i+2^{n-1}}=F_i-F_{i+2^{n-1}} \]

时间复杂度 \(O(n2^n)\)

Fifth. 逆变换

对照上面式子易得(留给读者思考)

Part 3. 模板题

核心代码如下

void fwtOr(ll *a,int n,int type) {
	for(int i=1; i<(1<<n); i<<=1)
		for(int j=0; j<(1<<n); j+=(i<<1))
			for(int k=0; k<i; ++k)
				(a[j+k+i]+=type*a[j+k])%=P;
}
void fwtAnd(ll *a,int n,int type) {
	for(int i=1; i<(1<<n); i<<=1)
		for(int j=0; j<(1<<n); j+=(i<<1))
			for(int k=0; k<i; ++k)
				(a[j+k]+=type*a[j+k+i])%=P;
}
void fwtXor(ll *a,int n,int type) {
	for(int i=1; i<(1<<n); i<<=1)
		for(int j=0; j<(1<<n); j+=(i<<1))
			for(int k=0; k<i; ++k) {
				ll u=a[j+k],v=a[j+k+i];
				a[j+k]=(u+v)%P;
				a[j+k+i]=(u-v)%P;
				if(type==-1) {
					(a[j+k]*=Pi2)%=P;
					(a[j+k+i]*=Pi2)%=P;
				}
			}
}

与Fast Walsh Transform 学习笔记 | FWT相似的内容:

Fast Walsh Transform 学习笔记 | FWT

本文中使用 \(\cap\) 表示按位与,用 \(\cup\) 表示按位或 Part 1. 与/或 卷积 First. 问题引入 给定长度为 \(2^n\) 的数列 \(A,B\),求 \(C_i = \sum_{j \cup k = i} A_j \times B_k\) 显然有 \(O(4^n)

[转帖]How fast are Unix domain sockets?

https://blog.myhro.info/2017/01/how-fast-are-unix-domain-sockets Jan 3, 2017 • Tiago Ilieve Warning: this is my first post written in English, after o

Poe – Fast AI Chat 一款集成AI工具

Poe – Fast AI Chat是由知名问答社区 Quora 开发的 AI 产品,提供实时在线与多个 AI 机器人交流的功能。目前,ChatGPT、Sage、Dragonfly、Claude 机器人都可以免费、无限制、实时使用,只需要一个邮箱即可注册。用户可以随时切换 AI 机器人而对话不中断,对话记录在线保存并且同步到客户端。Poe为用户提供了简单易用、高效便捷的智能交流服务,是企业和组织提高客户服务水平、优化工作流程的好帮手。

第二部分:关键技术领域的开源实践【内网穿透FRP】

FRP简介 FRP(Fast Reverse Proxy)作为一种高性能的内网穿透工具,支持 TCP、UDP、HTTP、HTTPS 等多种协议。可以将内网服务以安全、便捷的方式通过具有公网IP节点(云服务器)的中转暴露到公网。 为什么使用 FRP ? 以下是一些常见的企业级应用场景: 远程办公和远程

bazel学习

bazel学习 a fast, scalable, multi-language and extensible build system bazel就是一个编译打包工具,类似于make、cmake等 安装 ⚠️:Centos7系统安装bazel4 参考:https://docs.bazel.buil

【目标检测】Fast R-CNN算法实现

一、前言 2014年,Ross Girshick提出RCNN,成为目标检测领域的开山之作。一年后,借鉴空间金字塔池化思想,Ross Girshick推出设计更为巧妙的Fast RCNN(https://github.com/rbgirshick/fast-rcnn),极大地提高了检测速度。Fast

C#软件架构设计原则

软件架构设计原则 学习设计原则是学习设计模式的基础。在实际的开发过程中,并不是一定要求所有的代码都遵循设计原则,而是要综合考虑人力、成本、时间、质量,不刻意追求完美,要在适当的场景遵循设计原则。这体现的是一种平衡取舍,可以帮助我们设计出更加优雅的代码结构。 分别用一句话归纳总结软件设计七大原则,如下

推荐一套轻量级的开源图床系统:Light Fast Picture

如果您跟我一样平时有些博客的习惯,那么图片存储是否有困扰过你呢?今天就给大家推荐一款不错的开源图床系统:Light Fast Picture 它是一个基于koa + vue3.x + typescript实现的图床工具。它可以帮助用户快速上传图片到云端,并返回图片链接,方便用户在网页、社交媒体等平台

在线问诊 Python、FastAPI、Neo4j — 提供咨询接口服务

目录构建服务层接口路由层PostMan 调用 采用 Fast API 搭建服务接口: https://www.cnblogs.com/vipsoft/p/17684079.html Fast API 文档:https://fastapi.tiangolo.com/zh/ 构建服务层 qa_servi

使用部分写时复制提升Lakehouse的 ACID Upserts性能

## 使用部分写时复制提升Lakehouse的 ACID Upserts性能 译自:[Fast Copy-On-Write within Apache Parquet for Data Lakehouse ACID Upserts](https://www.uber.com/en-ZA/blog/f