集合幂级数笔记(施工中,勿入)
符号声明:\(\subseteq\) 表示包含于,\(\subset\) 表示真包含于。
定义
我们令 \(U=\{0,\dots,n-1\}\)。
一个集合幂级数 \(f\) 是对于全集 \(U\) 和环 \(R\),一个 \(2^U\to R\) 的映射,对于 \(S \subseteq U\),记 \(f_{S}\) 表示 \(S\) 所对应的值。
在 OI 中,\(R\) 一般取对质数 \(P\) 取模的 \(\mathbb{F}_P\)。
也写作
这里的 \(x^{S}\) 完全是形式记号,这个写法仿照了形式幂级数,但不应该看作一个关于 \(x\) 的函数。
运算
我们需要运算,首先和差加法逆是好定义的。
对于两个集合幂级数 \(f,g\),定义它们的和 \(f+g\) 为
对于集合幂级数 \(f\),定义加法逆 \(-f\) 为
对于集合幂级数 \(f,g\),定义减法 \(f-g\) 为
接下来考虑两个集合幂级数的乘法,也就是卷积。
我们知道,对于两数列 \(a,b\),其卷积 \(a\ast b=c\) 为
这里我们可以把 \(x+y=i\) 看成一个抽象的形式,即对于任意二元函数 \(\operatorname{op}(x,y)\),我们都可以定义
为 \(a,b\) 的某种卷积。
普通序列卷积中,这个运算是加法,对于集合我们尝试定义「加法」,考虑集合并。
这就是集合并卷积,因为一般用二进制数表示集合,集合并就是 OR 运算,所以也称 OR 卷积。
求集合并卷积是简单的,可以考虑高维前缀和(这被称作快速莫比乌斯变换),定义 \(\operatorname{FMT}(f)_S=\sum_{T \subseteq S}f_T\),不难有
对于多个的 OR 卷积,容易发现可以先全部 FMT,乘起来后再逆 FMT。
对于逆 FMT,记作 \(\operatorname{FMT}^{-1}\),我们要用到子集反演:
证明:
FMT 和 IFMT 实现:
typename<typename T>
void FMT(int n,T *a){
for(int j=0;j<n;++j){
for(int i=0;i<(1<<n);++i){
if((i>>j)&1){
a[i]+=a[i^(1<<j)];
}
}
}
}
typename<typename T>
void IFMT(int n,T *a){
for(int i=0;i<(1<<n);++i){
a[i]=((__builtin_popcount(i)&1)?-a[i]:a[i]);
}
for(int j=0;j<n;++j){
for(int i=0;i<(1<<n);++i){
if((i>>j)&1){
a[i]+=a[i^(1<<j)];
}
}
}
for(int i=0;i<(1<<n);++i){
a[i]=((__builtin_popcount(i)&1)?-a[i]:a[i]);
}
}
子集卷积(无交并卷积)
接下来是重要的子集卷积,我们定义
这里 \(\sqcup\) 意思是无交并。
这看起来比较困难,因为我们并不能通过一个简单的变换将其转化成逐位相乘。
但是注意到 \(L\sqcup R=S\Leftrightarrow L\cup R=S\land |L|+|R|=|S|\),我们可以将 \(R\) 替换为 \(R[x]\),对于 \(S\),定义新的 \(f^{\prime}_S=f_S x^{|S|}\)。
那么我们可以对这样替换后的 \(f^{\prime},g^{\prime}\) 做一遍 OR 卷积,然后对于每个 \(S\),只取 \(|S|\) 次的系数。
多项式乘法朴素实现是 \(n^2\) 的,于是复杂度 \(\Theta(n^22^n)\) 当然你也可以用 FFT,但是在 \(n\) 较小时常数是更劣的。
其它卷积?
如果我们考虑集合交,便能得到 AND 卷积,做法只是把前缀和改为后缀和。
如果考虑集合对称差(\(A \oplus B=(A\cup B)\setminus(A\cap B)\)),就得到异或卷积,这里有一个分治做法:
OR 卷积、AND 卷积和异或卷积是 FWT 处理的问题。
集合幂级数复合(exp,ln,求逆)
接下来我们定义 \(k\) 次幂为 \(f^k=\underbrace{f\times f \dots \times f}_{k \text{个} f}\),对于一个形式幂级数 \(H(x)=\sum_{i \ge 0}h_ix^i\),定义复合
是一个集合幂级数。
我们令 \(f^{\prime}_S=f_Sx^{|S|},\overline{f}=\operatorname{FMT}(f^{\prime})\),有
这样就有 \(\overline{H(f)}_S=H(\overline{f}_S)\)。
我们可以先将 \(f\) 转成 \(\overline{f}\),对于每一个 \(S\) 计算 \(g_S=H(\overline{f}_S)\),省略 \(n\) 次以上的项,再得到 \([x^{|S|}]\operatorname{FMT}^{-1}(g)_S\)
根据最新科技,多项式复合在 \(\mathbb{F}_{998244353}\) 下可以做到 \(\Theta(n \log^2 n)\),我们得到 \(\Theta(n \log^2 n 2^n)\) 的集合幂级数复合。
当然实际上用不着这个对于 \(h(x)=\exp(x)\) 和 \(\ln(1+x)\) 以及 \(\dfrac{1}{1-x}\) 的情况下,直接 \(\Theta(n^2)\) 求就可以了。
呃,怎么 \(\Theta(n^2)\) exp,ln,求逆?
如果你不知道什么是 exp,ln,求逆
如何 exp,ln,求逆
求逆
给你 \(A\),要求
于是
ln
\(B(x)=\ln A(x)\),于是 \(B^{\prime}(x)=\dfrac{A^{\prime}(x)}{A(x)}\),可以直接求逆再积分。
但这样子常数太大,我们可以直接递推
exp
\(B(x)=\exp(A(X))\),于是 \(B^{\prime}(x)=A^{\prime}(x)B(x)\)。
部分 exp
我们定义 \(\exp_k(x)=\sum_{i=0}^{k}\dfrac{x^i}{i!}\)。
令 \(C(x)=\dfrac{A(x)^k}{k!}\)(不难直接求得)
其中 exp 是有重要的组合意义的,其表示将一个集合无序拆分成若干子集,所有拆分方案的权值和。
你已经掌握了集合幂级数的基础知识,接下来是一些练习。
一般记 \(e(S)\) 表示在一个图中点集 \(S\) 的导出子图边数,\(e(S,T)\) 表示所有 \(u \in S,v\in T\) 的边 \((u,v)\) 数量(一般假设 \(S\cap T=\varnothing\)),在无向图中,有 \(e(S,T)=e(S\cup T)-e(S)-e(T)\)。
数 DAG 定向 CF1193A
给你一个有向图 \(G=(V,E)\),你需要对一些边改变方向,使得定向后图为 DAG,求对于所有合法的定向方案改变的边数量之和。
保证两点之间最多一条边。(忽略方向)
做法
首先考虑对于一个改变边的方案 \(E^{\prime}\),我们取其补集 \(E\setminus E^{\prime}\) 也可以得到一个合法方案,且改变边的数量和为 \(m\)。
将原图视为无向图,我们只需求出有多少种定向方案为 DAG 再乘上 \(\dfrac{m}{2}\) 即可。
令 \(f_S\) 表示将 \(S\) 的导出子图内所有边定向且为 DAG 的方案数。
考虑枚举出度为 \(0\) 的点集 \(T\),首先 \(T\) 要为独立集,然后所有从 \(S\setminus T\) 到 \(T\) 的边的方向被唯一确定,似乎有
但这显然是错的,因为我们会重复计数,对于恰有 \(|\overline{T}|\) 个点为出度为 \(0\) 点的情况下,会被重复计数 \(2^{|\overline{T}|}-1\) 次。
考虑容斥,我们添加上容斥系数 \((-1)^{|T|-1}\),这样因为
就恰被计算了一次。
这个技巧被称为 DAG 容斥。
这样朴素做是 \(\Theta(3^n)\) 的,可以通过,但利用集合幂级数可以做到更优的复杂度。
这个转移是半在线的,后面会讲如何做半在线子集卷积,但这里可以直接推式子。
我们记 \(g_S=[S\text{ 是独立集且非空}](-1)^{|S|-1}\) 那么有
于是有 \(f=\dfrac{1}{1-g}\),直接求逆即可。
数 DAG 生成子图
给你一个有向图,求有多少个生成子图是 DAG。
做法
和之前差不多,令 \(f_S\) 表示点集 \(S\) 以内的 DAG 生成子图数,枚举出度为 \(0\) 点,有转移:
由于这里是有向边,所以只能 \(\Theta(3^n)\)。
数强连通生成子图 CTT2014 D1T2 主旋律
给你一个有向图,求有多少个生成子图强连通。
做法
考虑一个想法,用 \(2^m\) 减去所有有两个以上强连通分量的子图。
那么假设已经知道好了强连通分量的划分,那么内部就是强连通子图,外部就是 DAG 子图计数。
数连通生成子图
给你一个无向图 \(G=(V,E)\),求连通生成子图数量。
做法
似乎并不好直接刻画连通性,但我们知道
假设我们已经知道了对于点集 \(S\) 内部的连通生成子图数,令 \(g\) 表示 \(S\) 内部生成子图数,有
反过来就有 \(f=\ln g\),而 \(g_S=2^{e(S)}\),直接做集合幂级数 ln 即可。
这里有一个启示,对于生成子图,我们一般考虑将其组合得到简单的,再反过来推导。
数连通二分生成子图 at_arc205_f
给你一个图 \(G=(V,E)\),求有多少个连通的生成子图是二分图。
解法
注意到
染色是为了保证只计数一次。
令 \(g_S\) 表示 \(S\) 以内二分生成子图且染色的方案数,\(f_S\) 表示 \(S\) 以内连通二分生成子图且染色的方案数,所求即 \(\dfrac{f_U}{2}\)。
考虑如何求 \(g\)。
有
直接子集卷积。
数点双连通生成子图
给你一个无向图 \(G=(V,E)\),求点双连通生成子图数量。
做法
我们考虑如何从点双连通分量得到连通图。
你可能会考虑耳分解之类的东西,但其实很简单。
我们依此扫每个点,每次将所有包含该点的点双连通分量合并就能得到连通图。
容易发现这是一一对应的。
假设我已经知道了对于每个点集 \(S\),点双连通生成子图的个数 \(f_S\),然后我们扫 \(i=1\dots n\),每一次操作就是取出所有包含 \(i\) 的点集 \(S\),去掉 \(i\) 之后进行 exp,然后再加回 \(i\) 放回 \(f\)。这被称作点双连通-连通变换。
我们考虑逆操作,取出所有包含 \(i\) 的点集 \(S\),去掉 \(i\) 之后 ln,加上 \(i\) 再放回去。
单次 ln 是 \(O(n^2 2^n)\) 的,复杂度 \(\Theta(n^3 2^n)\)。
数边双连通生成子图
给你一个无向图 \(G=(V,E)\),求边双连通生成子图数量。
做法1
我们可以这么刻画边双连通图。
- 点双大小不为 2 的连通图。
于是我们可以先求出点双连通生成子图数,然后去掉大小为 2 的,反过来再跑一遍正的,复杂度 \(\Theta(n^3 2^n)\)。
做法2
上面这个做法不够通用,我们尝试给出所谓边双连通-连通变换。
首先对于一张连通无向图,如果将所有边双缩起来,图会形成一棵树,树上的边是原图的割边。
考虑一个反过来的问题:假设给原图所有子集 \(S\subseteq U\) 均赋了权重 \(a_S\),并定义一张连通子图的权值是其所有边双对应的 \(a\) 之积,并且我们还已经对所有 \(S\) 知道了 \(S\) 的边双连通生成子图数量是 \(b_S\),如何求原图所有生成子图的权值和。
我们仿照之前思路,依次加点,每一次考虑所有编号 \(\le i\) 的 \(S\) 的生成子图的割边,再将所有经当前考虑的割边所连接的边双合并。
设考虑到 \(u\) 时的集合幂级数为 \(p_u\),首先 \((p_0)_S=a_Sb_S\)。
那么考虑由 \(p_{u-1}\) 转移到 \(p_u\),即加入所有两端编号最大值为 \(u\) 的割边。
先考虑加之前,此时对于点集 \(S\) 被分为 \(P_1,P_2,\dots,P_k\) 几块,假设 \(u \in P_1\)。
那么对于这样一个划分,贡献为
半在线卷积
有的时候我们并不能直接求逆解决,这时我们需要半在线。
例题 P4221 州区划分
\(n\) 座城市,每座城市有 \(w_i\) 人口,你要有序划分成若干州 \(\{V_1,\dots,V_k\}\),每个州非空且导出子图不是欧拉图,定义一个州的满意度为
定义一个划分方案的权值为所有州满意度的乘积。
求所有划分方案的权值和。
解法
首先欧拉图的限制是无关紧要的,直接判就可以了。
直接令 \(W_S=(\sum_{u \in S}w_u)^p\),有转移
这里很烦的是带了一个 \(\dfrac{1}{W_S}\) 导致不能直接写成集合幂级数的形式。
回顾一下怎么求子集卷积的,每个 \(S\) 上维护了一个多项式,注意到子集卷积时每项次数只会变大。
于是我们枚举次数 \(0\dots n\),每次跑一个 OR 卷积就可以了。1.

浙公网安备 33010602011771号