本文参考了 Dance of Faith 大佬的博客

我们定义集合并卷积

\[h_{S} = \sum_{L \subseteq S}^{} \sum_{R \subseteq S}^{} [L \cup R = S] f_{L} * g_{R}
\]

最暴力的时候只能 \(O(4^n)\) 完成,进行 一些优化 可以在 \(O(3^n)\) 内完成,当然我们可以在 \(O(n 2^n)\) 利用 \(FMT\) 或者 \(FWT\) 内快速处理。

\(FMT\) 原理更好理解,就介绍此种方式。

具体来说,类似与 \(FFT\) 我们把 \(f,g\) 求点值,然后点值相乘后再插值变化回去。因为要快速实现这个过程,我们可以考虑利用 快速莫比乌斯变换快速莫比乌斯反演 实现。

定义

定义 \(f\) 的莫比乌斯变换 \(\hat{f}\) ,满足 \(\hat{f_S} = \sum_{T \subseteq S} f_T\) 。(也就是 \(\hat{f}\) 是原来函数 \(f\) 的子集和)

定义 \(\hat{f}\) 的莫比乌斯反演 \(f\) ,利用容斥原理可以得到 \(f_S = \sum_{T \subseteq S} (-1)^{|S| - |T|} f_{T}\) 。

考虑为什么这个形式满足集合并卷积。

\[h_{S} = \sum_{L \subseteq S}^{} \sum_{R \subseteq S}^{} [L \cup R = S] f_{L} * g_{R}
\]

左右同时做莫比乌斯变换。

\[\begin{aligned}
\hat{h_{S}} &= \sum_{T \subseteq S} \sum_{L \subseteq T} \sum_{R \subseteq T} [L \cup R = T] f_{L} * g_{R}\\
&= \sum_{L \subseteq S} \sum_{R \subseteq S} [L \cup R \subseteq S] f_{L} * g_{R}
\end{aligned}
\]

由于 \([L \cup R \subseteq S] = [L \subseteq S][R \subseteq S]\) ,也就有

\[\begin{aligned}
\hat{h_{S}} &= \sum_{L \subseteq S} \sum_{R \subseteq S} f_{L} * g_{R}\\
&= (\sum_{L \subseteq S}f_L)(\sum_{L \subseteq S}g_R)\\
&=\hat{f_L} * \hat{g_R}
\end{aligned}
\]

证毕。

快速变换与反演

原理讲解

上面那两个集合和我们暴力做是 \(O(3^n)\) 的,可以进行优化。

考虑按 集合大小 分层递推。

令 \(\hat{f_{S}}^{(i)}\) 为 \(\sum_{T \subseteq S} [(S - T) \subseteq \{0, 1, 2, ..., i\}] f_{T}\) ,有 \(\hat{f}_S^{(0)} = f_S\) 。

那么对于不包含 \(\{i\}\) 的集合 \(S\) ,满足 \(\hat{f_{S}}^{(i)} = \hat{f_{S}}^{(i - 1)}\) ,那么它的贡献就是

\[\hat{f}_{S \cup \{i\}}^{(i)} = \hat{f}_{S}^{(i - 1)} + \hat{f}_{S \cup \{i\}}^{(i - 1)}
\]

这样,递推 \(n\) 轮后 \(\hat{f}^{(n)}_S\) 就包含所有情况,即为所求变换。

对于莫比乌斯反演的话,同样递推,不断减掉就行了。

代码实现

void FMT(int *f, int opt) {
for (int j = 0; j < n; ++ j)
for (int i = 0; i < (1 << n); ++ i) if (i >> j & 1)
f[i] += opt * f[i ^ (1 << j)];
}

子集卷积

原理讲解

我们定义 \(f\) 与 \(g\) 的子集卷积 \(f * g = h\) 。

\[h_{S} = \sum_{L \subseteq S}^{} \sum_{R \subseteq S}^{} [L \cup R = S, L \cap R = \varnothing] f_{L} * g_{R}
\]

其实就是

\[h_S = \sum_{T \subseteq S} f_T * g_{S - T}
\]

刚刚讲的子集并卷积为何不行呢?因为有 \([L \cap R = \varnothing]\) 的这个限制。

如何去掉这个限制呢,我们多记一维集合大小,也就是 \(f_{i, S}\) 表示有 \(i\) 个元素,集合表示为 \(S\) 。

显然当且仅当 \(i = |S|\) 时是正确的,我们先做 \(FMT\) 。

所以递推的时候就是 \(h_{i + j, S} = \sum_{i, j} f_{i, S} * g_{j, S}\) ,其实是个多项式乘法。

由于前面对于 \(n\) 个函数进行 \(FMT\) 需要 \(O(n^2 2^n)\) 的复杂度。

这里 \(FFT\) 也优化不了复杂度(而且由于常数会慢很多),那么直接暴力卷积就好了。

代码实现

for (int i = 0; i <= n; ++ i) {
for (int j = 0; i + j <= n; ++ j)
for (int S = 0; S < (1 << n); ++ S)
h[i + j][S] += f[i][S] * g[j][S];
}

最后我们要求 \(S\) 的子集卷积的结果,直接用 \(h_{\text{bitcount(S)}, S}\) \(IFMT\) 的。

子集逆卷积

原理讲解

我们有时候需要做子集卷积意义下的除法或者相关运算。

比如对于两个函数 \(f * g = h\) ,我们已知 \(g, h\) 要求 \(f\) 。

那么就是 \(f = h * g^{-1}\) 。其实就是要求 \(g^{-1}\) 在子集卷积意义下的结果。

同样我们只需要考虑 \(FMT\) 之后的结果。

由于对于每一位我们做的是多项式下的乘法。其实就是对于每一位求的 \(g^{-1}\) 就是多项式求逆后的结果。

同样对于别的运算也是多项式后的结果。

但是写那个 \(O(n \log n)\) 的倍增多项式求逆显然十分地麻烦,可以考虑 \(O(n ^ 2)\) 递推。

令 \(g^{-1} = t\) 假设我们求出 \(t_{0, 1, \cdots, i - 1}\) ,要求 \(t_i\) 。\((t_0 = g_0^{-1})\) 。

我们可以把 \(g_i\) 减去 \(t\) 和 \(g\) 前 \(i - 1\) 项做卷积后的第 \(i\) 项的值,就是所求的 \(t_i\) 。

这样就可以解决啦qwq

代码

inline void Inv(int *f) {
tmp[0] = fpm(f[0], Mod - 2);
for (int i = 0; i <= n; ++ i) {
inv[i] = tmp[i];
for (int j = 0; i + j <= n; ++ j)
tmp[i + j] -= inv[i] * f[j];
}
}

FMT 与 子集(逆)卷积的更多相关文章

  1. FMT 和 子集卷积

    FMT 和 子集卷积 FMT 给定数列 $ a_{0\dots 2^{k}-1} $ 求 $ b $ 满足 $ b_{s} = \sum_{i\in s} a_i $ 实现方法很简单, for( i ...

  2. 逆卷积的详细解释ConvTranspose2d(fractionally-strided convolutions)

    1.首先先定义进行卷积的参数: 输入特征图为高宽一样的Hin*Hin大小的x 卷积核大小kernel_size 步长stride padding填充数(填充0) 输出特征图为Hout*Hout大小的y ...

  3. @总结 - 2@ 位运算卷积/子集卷积 —— FWT/FMT

    目录 @0 - 参考资料@ @1 - 异或卷积概念及性质@ @2 - 快速沃尔什正变换(异或)@ @3 - 快速沃尔什逆变换(异或)@ @4 - 与卷积.或卷积@ @5 - 参考代码实现@ @6 - ...

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

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

  5. [WC2018]州区划分(状压DP+FWT/FMT)

    很裸的子集反演模板题,套上一些莫名其妙的外衣. 先预处理每个集合是否合法,再作显然的状压DP.然后发现可以写成子集反演的形式,直接套模板即可. 子集反演可以看这里. 子集反演的过程就是多设一维代表集合 ...

  6. LOJ #2542. 「PKUWC 2018」随机游走(最值反演 + 树上期望dp + FMT)

    写在这道题前面 : 网上的一些题解都不讲那个系数是怎么推得真的不良心 TAT (不是每个人都有那么厉害啊 , 我好菜啊) 而且 LOJ 过的代码千篇一律 ... 那个系数根本看不出来是什么啊 TAT ...

  7. 『TensotFlow』转置卷积

    网上解释 作者:张萌链接:https://www.zhihu.com/question/43609045/answer/120266511来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业 ...

  8. pytorch 不使用转置卷积来实现上采样

    上采样(upsampling)一般包括2种方式: Resize,如双线性插值直接缩放,类似于图像缩放,概念可见最邻近插值算法和双线性插值算法——图像缩放 Deconvolution,也叫Transpo ...

  9. 卷积生成对抗网络(DCGAN)---生成手写数字

    深度卷积生成对抗网络(DCGAN) ---- 生成 MNIST 手写图片 1.基本原理 生成对抗网络(GAN)由2个重要的部分构成: 生成器(Generator):通过机器生成数据(大部分情况下是图像 ...

随机推荐

  1. 国外线下技术俱乐部建设(1) - Belgrade Python技术俱乐部2019-01-25活动感悟

    这是<国外线下技术俱乐部建设>系列文章之一.   虽然之前接触过Belgrade的.NET技术俱乐部,但是它最近活动要春节后了. 出于观摩别人是怎么搞线下社区的心态,还有自己也有在用Pyt ...

  2. springmvc实现视频上传+进度条

    前台表单: <form id="uploadform" method="post" enctype="multipart/form-data&q ...

  3. 动态更新Icon

    动态更改图标主要用到activity-alias和PackageManager的setComponentEnabledSetting方法.具体步骤如下: 1.在AndroidManifest.xml中 ...

  4. Kotlin入门(32)网络接口访问

    手机上的资源毕竟有限,为了获取更丰富的信息,就得到辽阔的互联网大海上冲浪.对于App自身,也要经常与服务器交互,以便获取最新的数据显示到界面上.这个客户端与服务端之间的信息交互,基本使用HTTP协议进 ...

  5. react基础语法二

    这里只是对自己的学习进行一次总结,也是为了让自己以后如果长时间不使用快速记忆起来的笔记,如果想要学习,还是去官网看文档比较好一些.. 注意 下面的代码的 script标签的type类型都为 “text ...

  6. Python编写脚本(输出三星形状的‘*’符号)

    环境:python3.* 心得:个人认为脚本非我强项,以下效果可以有更简单解决方案,纯属练习逻辑. 方案一: s=1 while s<=10: #这是决定多少列,起始为1,大循环一圈即加一,就是 ...

  7. Nginx+uWSGI启动Django

    在之前的几篇博客中对Django的功能做了初步实践,这里链接贴一下: Django的安装和启动 Django之--网页展示Hello World! Django之--通过MVC架构的html模板展示H ...

  8. Win10 - MySQL 5.7 密码重置

    Win10 - MySQL 5.7 密码重置 所有行为均发生在系统管理员权限的 Cmd 或 Powershell 下 注意! 本行为会导致数据库重置 # 重新安装 mysql 服务 mysqld -- ...

  9. CentOS7编译安装php7.1

    1.首先安装依赖包: yum install libxml2 libxml2-devel openssl openssl-devel bzip2 bzip2-devel libcurl libcurl ...

  10. Nginx负载均衡的4种方式 :轮询-Round Robin 、Ip地址-ip_hash、最少连接-least_conn、加权-weight=n

    这里对负载均衡概念和nginx负载均衡实现方式做一个总结: 先说一下负载均衡的概念: Load Balance负载均衡是用于解决一台机器(一个进程)无法解决所有请求而产生的一种算法. 我们知道单台服务 ...