小 Tips:在计算机语言中 \(\cap\) = & / and, \(\cup\) = | / or

First. 定义

定义长度为 \(2^n\) 的序列的 and 卷积 \(A = B * C\) 为 \(A_i=\sum_{j \cap k = i}{B_j \times C_k}\)

考虑快速计算

Second. 变换

定义长度为 \(2^n\) 的序列的 Zeta 变换

\[\hat A_i = \sum_{j \subseteq i}{A_j}
\]

即子集和

它具有一下性质:

\[\hat B_i \times \hat C_i
= \sum_{j \subseteq i} B_j \times \sum_{k \subseteq i} C_k
= \sum_{p \subseteq i} \sum_{j \cap k = p} B_j \times C_k
= \sum_{p \subseteq i} A_p = \hat A_i
\]

相当于 FFT 中的点值表示法,用以加速卷积过程

Third. 快速变换

暴力求解 \(\hat A\) 最优时间复杂度为 \(3^n\),考虑加速

考虑 子集DP ,有一篇很好的博客[1],这里大概讲解一下。

其实 \(\hat A\) 本质上是一个高维( \(n\) 维)前缀和

如果我们要求二维前缀和,显然可以通过一下代码实现:

// 1st
for(int i=1; i<=n; ++i)
for(int j=1; j<=m; ++j)
a[i][j]+=a[i-1][j];
// 2nd
for(int i=1; i<=n; ++i)
for(int j=1; j<=n; ++j)
a[i][j]+=a[i][j-1];

我们发现 1st 完成后 a[i][j] 表示的是 \(\sum_{k \le i} a_{k,j}\),即 \((i,j)\) 上方的元素和

那么 2nd 便是将 \((i,j)\) 左边操作后的 \(\sum_{k \le j} a_{i,k}\) 累加到 a[i][j] 中,即完成二维前缀和


下面拓展到三维前缀和

// 1st
for(int i=1; i<=n; ++i)
for(int j=1; j<=n; ++j)
for(int k=1; k<=n; ++k)
a[i][j][k]+=a[i-1][j][k];
// 2nd
for(int i=1; i<=n; ++i)
for(int j=1; j<=n; ++j)
for(int k=1; k<=n; ++k)
a[i][j][k]+=a[i][j-1][k];
// 3rd
for(int i=1; i<=n; ++i)
for(int j=1; j<=n; ++j)
for(int k=1; k<=n; ++k)
a[i][j][k]+=a[i][j][k-1];

类似地,1st,2nd 中处理除了第 k 平面中的二维前缀和,3rd 在立体空间中把他们加起来,成为三维前缀和


回到 Zeta 变换

\[\hat A_i = \sum_{j \subseteq i}{A_j}
\]

如果我们用二进制 \((x_{n-1}x_{n-2}x_{n-3}\ ...\ x_2x_1x_0)_2\) 表示集合 \(i\),二进制 \((y_{n-1}y_{n-2}y_{n-3}\ ...\ y_2y_1y_0)_2\) 表示集合 \(j\)

那么 \(\hat A_i\) 可以被视为 \(n\) 维前缀和,即

\[\hat A_i = \sum_{y_{n-1}\le x_{n-1},y_{n-2}\le x_{n-2},\ ...,\ y_1\le x_1,y_0\le x_0} A_j
\]

当然,下标都为 0/1

因此,我们有如下 Code:

for(int i=0; i<n; ++i)
for(int j=0; j<(1<<n); ++j)
if(j&(1<<i))
a[j]+=a[j^(1<<i)];

以上 Code 的 naive 形式为:

for(int i1=0; i1<2; ++i1) for(int i2=0; i2<2; ++i2) ... for(int in=0; in<2; ++in) if(i1>0) a[i1][i2][...][in]+=a[i1-1][i2][...][in];
for(int i1=0; i1<2; ++i1) for(int i2=0; i2<2; ++i2) ... for(int in=0; in<2; ++in) if(i2>0) a[i1][i2][...][in]+=a[i1][i2-2][...][in];
...
for(int i1=0; i1<2; ++i1) for(int i2=0; i2<2; ++i2) ... for(int in=0; in<2; ++in) if(in>0) a[i1][i2][...][in]+=a[i1][i2][...][in-1];

不要质疑我代码编译不通过

因此,我们用 \(O(n2^n)\) 的时间复杂度解决了 Zeta 变换

Fourth. 逆变换

warning:此处不是 莫比乌斯反演

众所周知,前缀和的逆运算即为差分

我们发现,只需要先将最后一维差分,即可将序列处理为 \(n-1\) 维前缀和

for(int i1=0; i1<2; ++i1) for(int i2=0; i2<2; ++i2) ... for(int in=0; in<2; ++in) if(in>0) a[i1][i2][...][in]-=a[i1][i2][...][in-1];
...
for(int i1=0; i1<2; ++i1) for(int i2=0; i2<2; ++i2) ... for(int in=0; in<2; ++in) if(i2>0) a[i1][i2][...][in]-=a[i1][i2-2][...][in];
for(int i1=0; i1<2; ++i1) for(int i2=0; i2<2; ++i2) ... for(int in=0; in<2; ++in) if(i1>0) a[i1][i2][...][in]-=a[i1-1][i2][...][in];

但实际上因为前缀和都是无序的,因此我们直接正着做就可以啦

只需要把正变换的 += 改为 -= 就可以了

Fifth. 扩展

有时候,题目给的不是 \(\cap\) ,而是 \(\cup\) 怎么办?

那我们重定义 Zeta 变换 为:

\[\hat A_i = \sum_{i \supseteq j} A_j
\]

再推一下式子:

\[\hat B_i \times \hat C_i
=\sum_{i\supseteq j} B_j \times \sum_{i\supseteq k} C_k
=\sum_{i\supseteq j,i\supseteq k} B_j \times C_k
=\sum_{i\supseteq p} \sum_{j \cup k=p} B_j \times C_k
=\sum_{i\supseteq p} A_p
=\hat A_i
\]

变换即超集和,高维后缀和

求法也很简单,只用将源代码中的 if(j&(1<<i)) 该为 if(!(j&(1<<i))) 即可


是 \(\oplus\) 怎么办?

快去学 FWT 吧

Last. 例题

再送你一个并/交集的小口诀:下并或,上交与


  1. 高维前缀和总结(sosdp) - heyuhhh - 博客园 (cnblogs.com)

Fast Möbius Transform 学习笔记 | FMT的更多相关文章

  1. ios 控件代码transform学习笔记

    1.图片设置(平移,缩放,旋转) 创建一个transform属性 //按钮点击时,只能执行一次向上旋转 //派 M_PI_4 45度旋转 . CGAffineTransform transforms= ...

  2. css笔记 - transform学习笔记(二)

    transform转换 CSS transform 属于2D/3D上的转换.变形效果.他不是一个动画,他就是变形.比如正方形变平行四边形,再变圆形.都是形状变成另一个形状. 但是如果配合上transi ...

  3. FMT/FWT学习笔记

    目录 FMT/FWT学习笔记 FMT 快速莫比乌斯变换 OR卷积 AND卷积 快速沃尔什变换(FWT/XOR卷积) FMT/FWT学习笔记 FMT/FWT是算法竞赛中求or/and/xor卷积的算法, ...

  4. 「学习笔记」Fast Fourier Transform

    前言 快速傅里叶变换(\(\text{Fast Fourier Transform,FFT}\) )是一种能在\(O(n \log n)\)的时间内完成多项式乘法的算法,在\(OI\)中的应用很多,是 ...

  5. [原创]java WEB学习笔记52:国际化 fmt 标签,国际化的总结

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  6. [学习笔记&教程] 信号, 集合, 多项式, 以及各种卷积性变换 (FFT,NTT,FWT,FMT)

    目录 信号, 集合, 多项式, 以及卷积性变换 卷积 卷积性变换 傅里叶变换与信号 引入: 信号分析 变换的基础: 复数 傅里叶变换 离散傅里叶变换 FFT 与多项式 \(n\) 次单位复根 消去引理 ...

  7. [学习笔记] 多项式与快速傅里叶变换(FFT)基础

    引入 可能有不少OIer都知道FFT这个神奇的算法, 通过一系列玄学的变化就可以在 $O(nlog(n))$ 的总时间复杂度内计算出两个向量的卷积, 而代码量却非常小. 博主一年半前曾经因COGS的一 ...

  8. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十八章:立方体贴图

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十八章:立方体贴图 代码工程地址: https://github.c ...

  9. 快速傅里叶变换(FFT)学习笔记(其一)

    再探快速傅里叶变换(FFT)学习笔记(其一) 目录 再探快速傅里叶变换(FFT)学习笔记(其一) 写在前面 为什么写这篇博客 一些约定 前置知识 多项式卷积 多项式的系数表达式和点值表达式 单位根及其 ...

  10. 【OI向】快速傅里叶变换(Fast Fourier Transform)

    [OI向]快速傅里叶变换(Fast Fourier Transform) FFT的作用 ​ 在学习一项算法之前,我们总该关心这个算法究竟是为了干什么. ​ (以下应用只针对OI) ​ 一句话:求多项式 ...

随机推荐

  1. verilog注释及vscode插件terosHDL

    模型功能 实现代码的注释的方法 基于vscode的文档自动生成 模型框图 `timescale 1ns / 1ps /* */ // ********************************* ...

  2. KingbaseES运维案例之---数据库启动“could not open shared memory segment”

    ​ 案例说明: 在kylin系统下数据库启动出现"could not open shared memory segment xxxx"的故障,故障如下所示: 适用版本: Kingb ...

  3. Windows10系统重装教程

    .  

  4. mvn命令将 ueditor百度富文本编辑器 所需jar包上传到本地maven仓库

    1.需要的jar包位置 在解压后的路径中的jsp/lib下:(UEditor\jsp\lib) 2.打开命令行窗口 WIN+R 输入cmd并回车 直接在命令行输入如下命令:(一个一个输入运行,里面的路 ...

  5. #动态规划,组合计数,树状数组,前缀和#F 简单计数题&K 最简单的题

    先膜两位出题人 F 简单计数题 题目 有\(n\)个活动,预约期有\(k\)天,第\(j\)天YC可以获得\(a_j(1\leq a_j\leq n)\)张预约券, 他会在\(n\)个活动中等概率选择 ...

  6. Pandas高级教程之:Dataframe的重排和旋转

    目录 简介 使用Pivot 使用Stack 使用melt 使用Pivot tables 使用crosstab get_dummies 简介 使用Pandas的pivot方法可以将DF进行旋转变换,本文 ...

  7. C#利用自动化接口编写OPC客户端,OPC Client,源码直接放网盘

    引用:https://www.cnblogs.com/flh1/p/12409266.html 链接: https://pan.baidu.com/s/1Vs08c7qjShEc9GQ8dvCkdg ...

  8. 为 Hugging Face 用户带来无服务器 GPU 推理服务

    今天,我们非常兴奋地宣布 部署到 Cloudflare Workers AI 功能正式上线,这是 Hugging Face Hub 平台上的一项新服务,它使得通过 Cloudflare 边缘数据中心部 ...

  9. 华为帐号为AITO问界M5助力,打造懂你的智能座舱

    12月23日,在华为冬季旗舰新品发布会上,AITO问界M5正式发布.华为赋能的AITO问界M5搭载HUAWEI DriveONE纯电驱增程平台和HarmonyOS智能座舱,并且带来华为终端云服务软硬协 ...

  10. 使用yum安装unixODBC时报错怎么办

    使用 yum 安装 unixODBC 时报错怎么办 背景介绍 在使用 yum 安装 unixODBC 时,上报如下错误: [root@mc0-0002 odbc_connection]# yum in ...