遗憾的是 math 里面一直没有很好的讲这个东西……所以这次细致说说。

FWT 的本质

类似于多项式卷积中,利用 ntt 变换使得卷积 \(\to\) 点乘,fwt 也是类似的应用。

定义某种位运算 \(\oplus\),那么 fwt 处理的位运算卷积形如:

\[H = F * G \implies H_k = \sum_{i \oplus j = k} F_i G_j
\]

那么我们需要构造出一种变换,使得:

\[H = F * G \iff fwt(H) = fwt(F) \cdot fwt(G)
\]

暂时我们还不得而知如何变换,考虑设 \(c(i, j)\) 表示变换系数,那么有:

\[fwt(F)_i = \sum c(i, j) F_j
\]

那么对应的点积:

\[fwt(H)_k = \sum_i \sum_j c(k, i) F_i c(k, j) G_j = \sum_i c(k, i) H_i
\]

根据卷积定义:

\[\sum_i c(k, i) H_i = \sum_i c(k, i) \sum_{x \oplus y = i} F_x G_y = \sum_x \sum_y F_x G_y c(k, x \oplus y)
\]

对比:

\[\sum_x \sum_y F_x G_y c(k, x \oplus y) = \sum_i \sum_j c(k, i) F_i c(k, j) G_j
\]

我们可以得知:

\[c(k, x \oplus y) = c(k, x) c(k, y)
\]

这个等式便是 fwt 的核心。

另外,考虑到位运算每一位是独立的,那么 \(c(x, y)\) 非常重要的性质是可以按位考虑。也就是说:

\[c(i, j) = c(i_0, j_0) c(i_1, j_1) \cdots
\]

其中 \(i_k\) 表示 \(i\) 的第 \(k\) 位。

那么我们只需要构造出 \(c(0/1, 0/1)\) 即可。

不妨假设我们已经构造出了 \(c\),那么怎么求解呢?

类似 ntt 的考虑,分治:

\[fwt_i = \sum c(i, j) F_j = \sum_{j = 0}^{(n / 2) - 1} c(i, j) F_j + \sum_{j = n / 2}^{n - 1} c(i, j) F_j
\]

将最高位拆出来,分别记为 \(i', j'\):

\[fwt_i = c(i_0, 0) \sum_{j = 0}^{(n / 2) - 1} c(i, j) F_j + c(i_0, 1) \sum_{j = n / 2}^{n - 1} c(i, j) F_j
\]

于是分半之后:

\[fwt(F)_i = c(i_0, 0) fwt(F_0)_i + c(i_0, 1) fwt(F_1)_i
\]

于是可以 \(O(n)\) 的合并两个规模减半的东西了,于是总复杂度 \(O(w 2^w)\),其中 \(w\) 是位数。

对于逆变换,将 \(c\) 求个逆,变换回去即可。

FWT 的构造

现在我们对于 \(\texttt{or, and, xor}\) 尝试构造其 \(c\) 矩阵。

\(\texttt{or}\)

首先,注意到 \(c(0, 0) c(0, 0) = c(0, 0 | 0)\),于是 \(c(0, 0) = 0/1\)。

同理,不难得出 \(c(0/1, 0/1) \in \{0, 1\}\)。

考虑 \(c(0, 0) c(0, 1) = c(0, 1)\) 可以得出 \(c(0, 0) = c(0, 1) = 1\) 或者 \(c(0, 1) = 0\)。

同理考虑 \(c(1, 0) c(1, 1) = c(1, 1)\) 也可以知道 \(c(1, 1) = 0\) 或者 \(c(1, 0) = c(1, 1) = 1\)。

注意到需要构造出的矩阵有逆,那么只能是:

\[\begin{bmatrix}
1 & 1 \\ 1 & 0
\end{bmatrix} \text{或者}
\begin{bmatrix}
1 & 0 \\ 1 & 1
\end{bmatrix}
\]

值得注意的是,第二种矩阵 \(c(i, j)\) 对应的等式为 \([i \& j = j]\),也就是说:

\[fwt_i = \sum_{i \& j = j} F_j = \sum_{j \subseteq i} F_j
\]

相当于子集求和!

void fwtor(int n, int inv = {1, -1}) {
for (int u = 2, k = 1; u <= n; u <<= 1, k <<= 1)
for (int i = 0; i < n; i += u)
for (int j = 0; j < k; ++j)
fwt[i + j + k] += fwt[i + j] * inv;
}

\(\texttt{and}\)

首先还是注意到 \(c(0/1, 0/1) \in \{0, 1\}\)。

考虑 \(c(0, 0) c(0, 1) = c(0, 0)\) 得出 \(c(0, 0) = 0\) 或者 \(c(0, 0) = c(0, 1) = 1\)。

同理考虑 \(c(1, 0) c(1, 1) = c(1, 0)\) 得出 \(c(1, 0) = 0\) 或者 \(c(1, 0) = c(1, 1) = 1\)。

那么还是:

\[\begin{bmatrix}
1 & 1 \\ 0 & 1
\end{bmatrix} \text{或者}
\begin{bmatrix}
0 & 1 \\ 1 & 1
\end{bmatrix}
\]

值得注意的是,第一种矩阵 \(c(i, j)\) 对应的是 \([i \& j = i]\),也就是说:

\[fwt_i = \sum_{i \& j = j} F_j = \sum_{i \subseteq j} F_j
\]

相当于超集求和!

void fwtand(int n, int inv = {1, -1}) {
for (int u = 2, k = 1; u <= n; u <<= 1, k <<= 1)
for (int i = 0; i < n; i += u)
for (int j = 0; j < k; ++j)
fwt[i + j] += fwt[i + j + k] * inv;
}

\(\texttt{xor}\)

考虑对于任意 \(x, y \in \{0, 1\}\) 存在 \(c(0, 0) c(x, y) = c(x, y)\),那么一定存在 \(c(0, 0) = 1\),否则 \(c(1, 1) = c(1, 0) = 0\) 显然没有逆,不可行。

考虑 \(c(0, 1) c(0, 1) = c(0, 0)\),那么 \(c(0, 1) = \pm 1\)。

\(c(1, 0) c(1, 0) = c(1, 1) c(1, 1) = c(1, 0)\),所以 \(c(1, 0) = 1\),否则 \(c(1, 1) = c(1, 0) = 0\) 则显然没有逆。

\(c(1, 1) c(1, 1) = c(1, 0)\),考虑到 \(c(1, 0) = 1\),那么自然 \(c(1, 1) = \pm 1\)。

所以可行的矩阵为:

\[\begin{bmatrix}
1 & 1 \\ 1 & -1
\end{bmatrix}
\text{或者}
\begin{bmatrix}
1 & -1 \\ 1 & 1
\end{bmatrix}
\]

注意到对于第一个矩阵,实际上的系数为 \((-1)^{|i \& j|}\)。啥也不相当于。

void fwtxor(int n, int inv = {1, 1/2}) {
for (int u = 2, k = 1; u <= n; u <<= 1, k <<= 1)
for (int i = 0; i < n; i += u)
for (int j = 0; j < k; ++j) {
int x = fwt[i + j], y = fwt[i + j + k];
fwt[i + j] = (x + y) * inv, fwt[i + j + k] = (x - y) * inv;
}
}

算法学习笔记(45): 快速沃尔什变换 FWT的更多相关文章

  1. 算法学习笔记(17): 快速傅里叶变换(FFT)

    快速傅里叶变换(FFT) 有趣啊,都已经到NOI的难度了,救命 首先,我们先讲述一下前置知识.已经明白的读者请移步后文 虚数 定义:\(z = a + bi\),其中 \(a, b \in R\ \ ...

  2. 一个数学不好的菜鸡的快速沃尔什变换(FWT)学习笔记

    一个数学不好的菜鸡的快速沃尔什变换(FWT)学习笔记 曾经某个下午我以为我会了FWT,结果现在一丁点也想不起来了--看来"学"完新东西不经常做题不写博客,就白学了 = = 我没啥智 ...

  3. 【学习笔鸡】快速沃尔什变换FWT

    [学习笔鸡]快速沃尔什变换FWT OR的FWT 快速解决: \[ C[i]=\sum_{j|k=i} A[j]B[k] \] FWT使得我们 \[ FWT(C)=FWT(A)*FWT(B) \] 其中 ...

  4. 快速沃尔什变换FWT

    快速沃尔什变换\(FWT\) 是一种可以快速完成集合卷积的算法. 什么是集合卷积啊? 集合卷积就是在集合运算下的卷积.比如一般而言我们算的卷积都是\(C_i=\sum_{j+k=i}A_j*B_k\) ...

  5. 集合并卷积的三种求法(分治乘法,快速莫比乌斯变换(FMT),快速沃尔什变换(FWT))

    也许更好的阅读体验 本文主要内容是对武汉市第二中学吕凯风同学的论文<集合幂级数的性质与应用及其快速算法>的理解 定义 集合幂级数 为了更方便的研究集合的卷积,引入集合幂级数的概念 集合幂级 ...

  6. Johnson算法学习笔记

    \(Johnson\)算法学习笔记. 在最短路的学习中,我们曾学习了三种最短路的算法,\(Bellman-Ford\)算法及其队列优化\(SPFA\)算法,\(Dijkstra\)算法.这些算法可以快 ...

  7. 算法学习笔记(3): 倍增与ST算法

    倍增 目录 倍增 查找 洛谷P2249 重点 变式练习 快速幂 ST表 扩展 - 运算 扩展 - 区间 变式答案 倍增,字面意思即"成倍增长" 他与二分十分类似,都是基于" ...

  8. Miller-Rabin 与 Pollard-Rho 算法学习笔记

    前言 Miller-Rabin 算法用于判断一个数 \(p\) 是否是质数,若选定 \(w\) 个数进行判断,那么正确率约是 \(1-\frac{1}{4^w}\) ,时间复杂度为 \(O(\log ...

  9. 算法学习笔记(9): 中国剩余定理(CRT)以及其扩展(EXCRT)

    扩展中国剩余定理 讲解扩展之前,我们先叙述一下普通的中国剩余定理 中国剩余定理 中国剩余定理通过一种非常精巧的构造求出了一个可行解 但是毕竟是构造,所以相对较复杂 \[\begin{cases} x ...

  10. 算法学习笔记(20): AC自动机

    AC自动机 前置知识: 字典树:可以参考我的另一篇文章 算法学习笔记(15): Trie(字典树) KMP:可以参考 KMP - Ricky2007,但是不理解KMP算法并不会对这个算法的理解产生影响 ...

随机推荐

  1. eclipse tomcat的一些错误

    eclipse tomcat运行错误 错误提示: Server Tomcat v7.0 Server at localhost was unable to start within 45 second ...

  2. 力扣661(java)-图片平滑器(简单)

    题目: 图像平滑器 是大小为 3 x 3 的过滤器,用于对图像的每个单元格平滑处理,平滑处理后单元格的值为该单元格的平均灰度. 每个单元格的  平均灰度 定义为:该单元格自身及其周围的 8 个单元格的 ...

  3. 五分钟学会使用 go modules(含在家办公使用技巧)

    导读:go modules 是 golang 1.11 新加的特性.如今 1.13 都已经发布了第 7 个小版本了,几乎所有大项目均已开始使用,这自然也包括 Kubernetes 生态中的众多项目.笔 ...

  4. Java应用结构规范

    ​简介:在Java程序开发中,命名和应用分层无疑是广大后端同胞的两大"痛点",本文提供一种基于领域模型的轻量级应用分层结构设计,供大家参考.下面按分层结构.分层明细.调用关系.各层 ...

  5. 这样才是代码管理和 Commit 的正确姿势! | 研发效能提升36计

    ​简介:效能提升从小习惯开始,这样才是代码管理和 Commit 的正确姿势! ​ 专栏策划|雅纯 志愿编辑|张晟 软件交付是以代码为中心的交付过程,其中代码的作用有几点:第一,最终的制品要交付成什么样 ...

  6. [FAQ] Win10 键盘输入的数字英文字体变宽, 胖英文, 如何处理

    输入法 点击右键,找到设置,点击进入. 开启 "全/半角切换" 快捷键为 "Shift + 空格",随后可以使用这个快捷键进行切换正常. Link:https: ...

  7. [Gin] 运行模式检测和设置 (mode.go)

    // 设置方式 gin.SetMode(gin.ReleaseMode) // 检测方式 if gin.Mode() == gin.DebugMode { } 更多相关信息,建议直接去看源代码. Re ...

  8. ASP.NET CORE 发布时不编译Views文件夹

    .net core 3.0正式版已经发布,目前整体相对来说已经稳定了,可以进行生产开发. 发布时默认情况下Views是直接编译成DLL文件(XXXXXX.Views.dll),日常开发维护过程中,经常 ...

  9. NopCommerce支持多种类型的数据库

    本文章的内容是根据本人阅读NopCommerce源码的理解,如有不对的地方请指正,谢谢. 阅读目录 1.类结构关系图 2.分析 3.NopCommerce应用 类结构关系图 分析 NopObjectC ...

  10. Blazor/Hybird 触屏下单程序调优笔记

    环境 Blazor Net8.0 + FreeSql + Bootstrap Blazor 组件 以下都是自己瞎琢磨的和官网资料搬运,肯定有不少错漏和不合理的地方,非常希望各位大佬评论区给我建议和意见 ...