集合幂级数相关论文阅读笔记

《集合幂级数的性质与应用及其快速算法》阅读笔记 & 《集合幂级数在子图计数问题上的应用》笔记

from 吕凯风 2015 年的论文 和 陈昕阳 APIO2025 的课件

为了研究以集合为状态的递推,本文提出了集合幂级数,它具有很多较好的性质,可以进行加速递推。

约定:

  • 设全集 \(U={1,2,\dots,n}\)。本文中所有集合 \(S\) 均满足 \(S\subseteq U\)
  • \(X\subseteq U\),则 \(2^X=\{S\mid S\subseteq X\}\)

1 定义

\(F\) 是一个域,则称映射 \(f:2^U\rightarrow F\)\(F\) 上的一个集合幂级数。在 OI 中,我们一般研究的域是 \(\mathbb{R},\mathbb{Z}_p\)

加法是容易定义的:设 \(f,g\) 为集合幂级数,定义 \(f+g=h\),其中 \(h\) 是一个集合幂级数,则对于 \(\forall S\)\(h_S=f_S+g_S\)。我们可以在 \(O(2^n)\) 求出两个集合幂级数的加减法。容易看出集合幂级数构成了加法交换群。

我们考虑如何表示一个集合幂级数。类似形式幂级数,对于集合幂级数 \(S\),我们用 \(f_Sx^S\) 来表示一个第 \(S\) 项系数为 \(f_S\),其余项均为 \(0\) 的集合幂级数 \(f\)。注意 \(f_Sx^S\) 现在和 \(f_S\times x^S\) 并不一样,因为 \(x^S\) 现在并无含义,在这里仅是为了方便表示的符号。

于是可以用 \(f=\sum\limits_{S\in 2^U} f_Sx^S\) 来表示一个集合幂级数。例如 \(f=3x^{\varnothing}+4x^{\{1\}}+2x^{\{1,2\}}\) 对应一个 \(f_\varnothing=3\)\(f_{\{1\}}=4\)\(f_{\{2\}}=0\)\(f_{\{1,2\}}=2\) 的集合幂级数 \(f\)

考虑如何定义乘法。对于集合幂级数 \(h=f\cdot g\),我们希望乘法对加法有分配律,因此 \(f\cdot g\) 需要满足

\[h=f\cdot g=\left(\sum\limits_{S\in 2^U}f_Sx^S\right)\left(\sum\limits_{S\in 2^U}g_Sx^S\right)=\sum\limits_{S\in 2^U}\sum\limits_{T\in 2^U} \left(f_Sx^S\right)\left(g_Tx^T\right) \]

考虑定义 \((f_Sx^S)(g_Tx^T)\),我们设一个 \(2^U\) 内的运算 \(*\),满足:

  • \(\forall U,V\in 2^U\)\(U*V=V*U\)(交换律);
  • \(\forall U,V,W\in 2^U\)\((U*V)*W=U*(V*W)\)(结合律);
  • \(\forall S\in 2^U\)\(S*\varnothing=S\)(单位元为 \(\varnothing\))。

那么我们就可以定义 \((f_Sx^S)(g_Tx^T)=(f_Sg_T)x^{S*T}\) 了,而且容易证明 \((2^U,\cdot)\) 是一个有单位元的半群。又因为 \((2^U,+)\) 是交换群,这样 \((2^U,+,\cdot)\) 就构成了一个环。此时我们可以将所有 \(c\in F\)\(c\) 看作 \(cx^{\varnothing}\),并且对于任意 \(S\in 2^U\) 都有 \(cx^S=c\cdot x^S\) 了。你还会发现 \(F\)\(2^U\) 的一个子环。

显然满足条件的运算 \(*\) 并不止一个,在 OI 中,我们通常研究三种运算:集合并卷积、对称差卷积、子集卷积。接下来我们将分别对这三种运算进行讨论。

2 集合并卷积

我们现在定义两个集合幂级数的乘积为集合并卷积。设 \(f=\sum\limits_{S\in 2^U}f_Sx^S\)\(g=\sum\limits_{S\in 2^U}g_Sx^S\),则定义 \(f\cdot g=h\)\(h\) 是一个集合幂级数,则满足 \(h_S=\sum\limits_{L\in 2^U}\sum\limits_{R\in 2^U}[L\cup R=S]f_Lg_R\)

如果我们从位运算的角度理解,他就是 \(h_x=\sum\limits_{i\text{ or } j=x}f_ig_j\)

直接求解的时间复杂度是 \(O(4^n)\),不能接受。

2.1 分治

从位运算的角度上看,集合的每一位都是独立的,考虑分治求解。

\(f=f^-+x^{\{n\}}\cdot f^+\)\(g=g^-+x^{\{n\}}\cdot g^+\),则

\[\begin{aligned} f\cdot g &= (f^-+x^{\{n\}}f^+)(g^-+x^{\{n\}}g^+) \\ &= f^-g^-+x^{\{n\}}f^-g^++x^{\{n\}}f^+g^-+x^{\{n\}}f^+g^+ \\ &= f^-g^-+x^{\{n\}}(f^-g^++f^+g^-+f^+g^+) \\ &= f^-g^-+x^{\{n\}}(f^-+f^+)(g^-+g^+)-x^{\{n\}}f^-g^- \end{aligned} \]

这样我们就转化了求 \(f^-g^-\)\((f^-+f^+)(g^-+g^+)\) 的问题,分治求解即可。则时间复杂度 \(T(n)=2T(n-1)+O(2^n)\),根据主定理,\(T(n)=O(n2^n)\)

2.2 快速莫比乌斯变换

分治的常数还是有点大了。我们对分治做法进行改进,就可以得到不需要递归的快速莫比乌斯变换。

考察这个分治。我们相当于将所有的 \(f_S(\{n\}\in S)\) 加上 \(f_{S\backslash \{n\}}\),相乘后再减去 \(f_{S\backslash \{n\}}\) 相乘后的结果。那么我们把这个过程拆开。

设一个集合幂级数的莫比乌斯变换为集合幂级数 \(\hat{f}\),其中 \(\hat{f}_S=\sum\limits_{T\subseteq S}f_T\)。反过来可以定义 \(\hat{f}\) 的莫比乌斯反演为 \(f\),由容斥原理,可以得到 \(f_S=\sum\limits_{T\subseteq S}(-1)^{|S|-|T|}\hat{f}_T\)

我们对 \(f\cdot g=h\) 等式两边同时进行莫比乌斯变换,有

\[\begin{aligned} \hat{h}_S &= \sum_{L\in 2^U}\sum_{R\in 2^U}[L\cup R\subseteq S]f_Lg_R \\ &= \sum_{L\subseteq S}\sum_{R\subseteq T}f_Lg_R \\ &= \left(\sum_{L\subseteq S}f_L\right)\left(\sum_{R\subseteq S}g_R\right) \\ &= \hat{f}_S\hat{g}_S \end{aligned} \]

我们想在想要求 \(h\),可以先求出 \(\hat{f}\)\(\hat{g}\),对应系数相乘得到 \(\hat{h}\),再通过莫比乌斯反演得到 \(h\)。求一个集合幂级数的莫比乌斯变换是容易的,直接递推即可。

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

回顾分治算法,这两种算法的本质是相同的,分治递归下去时进行了莫比乌斯变换,递归上来时进行了莫比乌斯反演。

3 集合对称差卷积

我们现在定义两个集合幂级数的乘积为集合对称差卷积。设 \(f=\sum\limits_{S\in 2^U}f_Sx^S\)\(g=\sum\limits_{S\in 2^U}g_Sx^S\),则定义 \(f\cdot g=h\)\(h\) 是一个集合幂级数,则满足 \(h_S=\sum\limits_{L\in 2^U}\sum\limits_{R\in 2^U}[L \oplus R=S]f_Lg_R\)

如果我们从位运算的角度理解,他就是 \(h_x=\sum\limits_{i\oplus j=x}f_ig_j\)

3.1 分治

\(f=f^-+x^{\{n\}}\cdot f^+\)\(g=g^-+x^{\{n\}}\cdot g^+\),则

\[\begin{aligned} f\cdot g &= (f^-+x^{\{n\}}f^+)(g^-+x^{\{n\}}g^+) \\ &= f^-g^-+x^{\{n\}}f^-g^++x^{\{n\}}f^+g^-+f^+g^+ \\ &= f^-g^-+f^+g^++x^{\{n\}}(f^-g^++f^+g^-) \\ &= \frac{(f^-+f^+)(g^-+g^+)+(f^--f^+)(g^--g^+)}{2} +x^{\{n\}}\frac{(f^-+f^+)(g^-+g^+)-(f^--f^+)(g^--g^+)}{2} \end{aligned} \]

这就转化为了求 \((f^-+f^+)(g^-+g^+)\)\((f^--f^+)(g^--g^+)(f^--f^+)(g^--g^+)\) 的问题,分治求解即可。则时间复杂度 \(T(n)=2T(n-1)+O(2^n)\),根据主定理,\(T(n)=O(n2^n)\)

3.2 快速沃尔什变换

首先注意到对于集合 \(S\)

\[[S=\varnothing]=\frac{1}{2^n}\sum_{T\in2^U}(-1)^{|S\cap T|} \]

这是一个非常重要的性质。那么你可以根据这个性质进行化简:

\[\begin{aligned} h_S &= \sum_{L\in 2^U}\sum_{R\in 2^U}[L\oplus R\oplus S=\varnothing] f_Lg_R\\ &= \sum_{L\in 2^U}\sum_{R\in 2^U}\frac{1}{2^n}f_Lg_R\sum_{T\in 2^U}(-1)^{|S\cap (L\oplus R\oplus S)|}\\ &= \sum_{L\in 2^U}\sum_{R\in 2^U}\frac{1}{2^n}f_Lg_R\sum_{T\in 2^U}(-1)^{|S\cap L|}(-1)^{|S\cap R|}(-1)^{|S\cap T|}\\ &= \frac{1}{2^n}\sum_{T\in 2^U}(-1)^{|S\cap T|}\left(\sum_{L\in 2^U}(-1)^{|S\cap L|}f_L\right)\left(\sum_{R\in 2^U}(-1)^{|S\cap R|}g_R\right) \end{aligned} \]

这启发我们定义出沃尔什反演的形式:设一个集合幂级数 \(f\) 的沃尔什变换为集合幂级数 \(\hat{f}\),则定义

\[\hat{f}_S=\sum\limits_{T\in 2^U}f_T(-1)^{|S\cap T|} \]

相应的,定义沃尔什反演

\[f_S=\frac{1}{2^n}\sum\limits_{T\in 2^U}\hat{f}_T(-1)^{|S\cap T|} \]

我们就得到了 \(\hat{h}_S=\hat{f}_S\hat{g}_S\)

我们想在想要求 \(h\),可以先求出 \(\hat{f}\)\(\hat{g}\),对应系数相乘得到 \(\hat{h}\),再通过沃尔什反演得到 \(h\)。求一个集合幂级数的沃尔什变换和沃尔什反演是容易的,直接递推即可。

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

不过由于我们需要在递推时乘以 \(\frac{1}{2^n}\),分治和这个算法都不能对特征为 \(2\)\(F\) 使用。

4 子集卷积

我们现在定义两个集合幂级数的乘积为子集卷积。设 \(f=\sum\limits_{S\in 2^U}f_Sx^S\)\(g=\sum\limits_{S\in 2^U}g_Sx^S\),则定义 \(f\cdot g=h\)\(h\) 是一个集合幂级数,则满足 \(h_S=\sum\limits_{L\in 2^U}\sum\limits_{R\in 2^U}[L \cup R=S][L\cap R=\varnothing]f_Lg_R\)

直接暴力枚举子集的时间复杂度是 \(O(3^n)\),考虑优化。

4.1 转化为集合并卷积

注意到 \([L\cup R=S][L\cap R=\varnothing]=[L\cup R=S][|L|+|R|=|S|]\)。我们可以考虑引入一个占位幂级数,用它的次数来限制 \(|L|+|R|=|S|\)

定义集合幂级数 \(f\)占位幂级数 \(\sigma\) 满足 \(\forall S\in 2^U\),对于 \(i\not= |S|\) 满足 \(\sigma_{i,S}=0\),且 \(\sigma_{|S|,S}=f_S\)。即 \(\sigma=\sum\limits_{S\in 2^U}\sum\limits_{i=|S|+1}^{\infty}\sigma_{i,S}z^{i}x^S\)

\(f\) 的占位幂级数为 \(\sigma\)\(g\) 的占位幂级数为 \(\tau\)\(g\) 的占位幂级数为 \(\delta\),于是有 \(\delta_{i}\leftarrow\sum\limits_{j+k=i}\sigma_{j}\cdot\tau_{k}\)

那么做法就很简单了:先把所有的 \(\sigma_i\)\(\tau_i\) 进行莫比乌斯变换,然后对应系数乘起来,然后变回去即可。

5 集合幂级数的复合

我们对于一个 \(f_\varnothing=0\) 的集合幂级数和一个多项式 \(h\),定义 \(g=h(f)\) 也是一个集合幂级数,它等于 \(\sum\limits_{i=0}^{\infty}h_if^i\)

这个无穷求和看上去很不好算,但考虑集合幂级数幂次的组合意义,由于 \((f\cdot f)_S=\sum\limits_{A\subseteq S} f_A\cdot f_{S\backslash A}\),这相当于将 \(S\) 这个集合划分为两个集合,然后对这两个集合的信息进行了合并。那么如果你的幂次 \(i>n\),就相当于将 \(n\) 个数划分为了 \(i\) 个部分,那其实 \(f^i\) 就都是 \(0\) 了。

回顾集合幂级数的乘法,我们要计算 \(f^i\),那么只需要计算出 \(\sigma^i\),即相当于要算 \(\sum\limits_{i=0}^{n}h_i\sigma^i\)。因为 \(\mathrm{FMT}(f_1\cdot f_2\dots f_k)_S=\prod_{i=1}^{k}\mathrm{FMT}(f_i)_S\),以及 \(\mathrm{FMT}(A+B)=\mathrm{FMT}(A)+\mathrm{FMT}(B)\),则有 \(\mathrm{FMT}(\sum\limits_{i=0}^{n}h_i\sigma^i)_S=\sum\limits_{i=0}^{n}h_i(\mathrm{FMT}(\sigma)_S)^i\)。这是形式幂级数的复合。

5.1 逐点牛顿迭代法

逐点牛顿迭代法可以在 \(O(n^22^n)\) 的时间复杂度内求出集合幂级数的复合,并且可适用于任意模数的泰勒展开。

论文上的说法我看不懂,这里写成人话。推倒重来,考虑设 \(g=\sum\limits_{i=0}^{\infty}\frac{h_i}{i!}f^i\)

普通求复合的时候这里需要求 \(1\sim n\) 的逆元,但我们可以考虑这个式子的组合意义,我们固定各个划分的顺序,就可以规避掉这个问题。

具体地,考虑设 \(dp_{i,j}\) 表示对于前 \(i\) 项,钦定还剩下 \(j\) 次子集卷积的答案。容易得到转移式 \(dp_{i,j}\leftarrow dp_{i-1,j}+dp_{i-1,j+1}\cdot f[2^{i},2^{i+1}-1]\),其中 \(f[l,r]\) 表示 \(f\) 仅在 \([l,r]\) 处有值。答案即为 \(dp_{n,0}\)

于是我们只需要做 \(\sum i(n-i)=O(n^2)\) 次子集卷积,总复杂度 \(O(n^32^n)\) 吗……?并非。\(f[2^i,2^{i+1}-1]\)\(i\) 次的,一次子集卷积的时间复杂度为 \(O(2^ii)\),时间复杂度 \(O(\sum i^2(n-i)2^i)=O(n^22^n)\),直接写的话常数比较大。

5.2 联系到背包

给你 \(n\) 个数 \(a_1,a_2,\dots,a_n\),称一种选数的方案 \(S\) 是合法的,当且仅当 \(\forall i,j\in S, i \not= j\)\(a_i\cap a_j=\varnothing\),它的价值为 \(\varphi(1+\sum a_i)\)。求所有合法方案的价值之和。

考虑写出答案式,选择一个集合 \(A\) 即为 \(x^A\),每个集合可以选或不选,即 \(\prod\limits_{i=1}^{n}(x^\varnothing+x^{A_i})\)

对其 \(\ln\)\(\exp\),有

\[\begin{aligned} \prod\limits_{i=1}^{n}(x^\varnothing+x^{A_i}) &= \exp\sum_{i=1}^{n}\ln(x^\varnothing+x^{A_i}) \\ &= \exp\sum_{i=1}^{n}\sum_{j=1}^{\infty}\frac{(-1)^{j-1}}{j!}(x^{A_i})^j \\ &= \exp\sum_{i=1}^{n}x^{A_i} \end{aligned} \]

这就是一个 \(\exp\) 的板子了。

Source:P6570 [NOI Online #3 提高组] 优秀子序列 的数据加强版本。

6 连通性问题

在此之前,先探讨一下 \(\exp\) 的组合意义。

我们有 \(\exp(F)=\sum\limits_{k=0}^{\infty} \frac{1}{k!}F^k\)。根据子集卷积的定义,\((F^k)_S\) 表示,将 \(S\) 划分为有序的 \(k\) 元组 \((S_1,S_2,\dots,S_k)\),其中每个 \(S_i\) 都是非空的,这些元组的值之积的和。我们往往不关心子集之间的顺序,于是我们需要将这个方案数除以 \(k!\)。因此 \(\exp(F)\) 的组合意义就呼之欲出了:将集合 \(S\) 划分成任意数量的不相交非空子集,求这些子集的权值的积之和。

形式化地,设 \([x^S]F(x)=f_S\)\([x^S]e^{F(x)}=g_S\),即

\[g_S=\sum_{\cup S_i=S,\sum |S_i|=k}\prod_{i=1}^{k}f_{S_i} \]

那么在一张图上,若 \([x^S]F(x)\) 为点集 \(S\) 的子图个数,\([x^S]G(x)\)\(S\) 的联通子图个数,则 \(\exp G=F\)

6.1 数联通子图

给定一个无向图 \(G\),求 \(G\) 有多少边子图是连通的。

直接套用 \(\exp\) 的组合意义即可。\(F\) 随便求吧,你每个边选不选都行。那么你就能通过 \(G=\ln F\) 知道 \(G\) 了。

相似例题:P11734 [集训队互测 2015] 胡策的统计

6.2 数与点联通的子图数量

给定一个无向图 \(G\),对每个 \(k\in [2,n]\) 求有多少张子图满足 \(1\)\(k\) 联通。

写出答案式:\(ans_k=\sum\limits_{\{1,k\}\subseteq S\subseteq U}g_Sf_{U\backslash S}\)。直接求即可。

Source:[ABC213G] Connectivity 2

6.3 数联通二分子图

给定一个无向图 \(G\),求 \(G\) 有多少边二分子图是连通的。

一个简单的想法是枚举左部点 \(S\),那么边的选取方案就是 \(2^{cross(S,U\backslash S)}\) 种。但是这样会算重,因为你发现一张图的黑白染色并不只有一个,设弱联通块的个数有 \(c\) 个,那么一张图会被算 \(2^c\) 次。

我们把一张图的价值定为 \(2^c\),设 \(g_S\) 表示 \(S\) 所有边二分子图的价值之和,\(f_S\) 表示所有联通边二分子图数量乘以 \(2\),于是有 \(g=\exp f\)

那么现在考虑如何快速算 \(g\)。设点集 \(S\) 的导出子图边数为 \(sum_S\),观察到有 \(g_S=\sum\limits_{T\subseteq S}2^{cross(T,S\backslash T)}=\sum\limits_{T\subseteq S} 2^{sum_S-sum_T-sum_{S\backslash T}}=2^{sum_S}\sum\limits_{T\subseteq S}2^{-sum_T-sum_{S\backslash T}}\),形成了一个子集卷积的形式。

一次子集卷积求出 \(g\),再用 \(f=\ln g\) 求出 \(f\),最后 \(\frac{f_U}{2}\) 即为答案。

Source:[ARC105F] Lights Out on Connected Graph

6.4 数杏仁子图

给定一个有向图 \(G\),源点 \(s\),汇点 \(t\),对于每个 \(u\),求 \(G\) 有多少杏仁子图包含边 \(s\rightarrow u\)

一张图被称为【杏仁】,当且仅当这张有向图的边集可以划分为 \(k\)\(s\)\(t\) 的路径,设第 \(i\) 条路径的点集为 \(S_i\),需满足 \(\forall i\not= j,S_i\cap S_j=\{s,t\}\)

首先考虑没有 \(s\rightarrow u\) 怎么做。你发现去掉 \(s,t\) 就是把若干链拼起来。设 \(f_S\) 表示选点集 \(S\) 拼成链的方案数,\(g_S\) 表示点集 \(S\) 的杏仁子图数。\(f_S\) 可以通过 dp 求出,那么你就可以通过 \(g=\exp f\) 算出 \(g\)

考虑加入限制 \(s\rightarrow u\),需要钦定 \(s\rightarrow u\) 是杏仁图上的边。可以将杏仁图拆成两个部分,以 \(u\) 为链顶的链 \(S_1\) 和其他链。其他链的方案数就是 \(g_{U\backslash S_1}\)。现在只需要求出 \(u\) 起始的单链方案数了。

考虑倒着 dp,设 \(dp_{S,u}\) 表示点集 \(S\) 组成的链,现在在点 \(u\),从 \(u\) 出发走到 \(t\) 的方案数。直接转移即可。

三个部分的时间复杂度都是 \(O(n^22^n)\),解决此题。

Source:QOJ #5411.【北大集训 2020】杏仁

7 强连通性、可达性、无环限制

对于有向图,我们可以探究一些强连通性、可达性、无环的限制。

在此之前,我们先来探究如何刻画一张 DAG。不难发现,一张 DAG 上总是存在零度点,而一次剥开每一层零度点就可以描述 DAG 的结构。

7.1 DAG 定向

给定一张无向图 \(G\),求有多少种定向方式使得得到的有向图无环。

有一个简单的想法,设 \(f_S\) 表示点集 \(S\) 子图的定向方案,每次枚举零度点集 \(T\subseteq S\),这需要有 \(\forall u,v\in T\)\(u\)\(v\) 之间没有连边,然后和 \(f_{S\backslash T}\) 进行计算。

但是如何保证 \(S\backslash T\) 的所有点入度不为 \(0\) 是个问题。显然的,可以考虑容斥,则有

\[f_S=\sum\limits_{T\subseteq S}(-1)^{|T|-1}[\forall u,v\in T,u\not\rightarrow v]f_{S\backslash T} \]

已经可以做到 \(O(3^n)\) 了。考虑设 \(g_S=\sum\limits_{T\subseteq S}(-1)^{|T|-1}[\forall u,v\in T,u\not\rightarrow v]\),那么 \(f=f\cdot g+1\),则 \(f=\frac{1}{1-g}\)。直接求逆即可。

习题:P6846 [CEOI 2019] Amusement Park

7.2 强连通子图计数

给定一张有向图 \(G\),求其强联通子图个数。

上述技巧还是可以继续沿用的。考虑缩点,非强连通图缩点后会形成一个 DAG,考虑对这个 DAG 计数。

不难想到设 \(f_S\) 表示将点集 \(S\) 的导出子图划分为若干无出度的 SCC,每个 SCC 加权和之和,\(g_S\) 表示 \(S\) 导出子图中强连通子图数量。考虑枚举 \(0\) 度点,于是有

\[\begin{aligned} 2^{(S,S)} &= \sum_{\varnothing \subsetneq T\subsetneq S}2^{(S-T,S-T)+(S-T,T)}f_T \\ f_S &= 2^{(S,S)}-\sum_{\varnothing \subsetneq T\subsetneq S}2^{(S-T,S)}f_T \end{aligned} \]

其中 \((S,T)\) 表示 \(S\)\(T\) 连边数量。那么你就可以 \(O(3^n)\) 求出 \(f\)。为什么不适用卷积优化呢,是因为这是有向图,\((S,T)\) 通常不能被很好的拆分出来。

接下来考虑求 \(g\)。先写出一个特别暴力的式子:

\[f_S = \sum_{k=1}^{n}\sum_{T_1\dots T_k \text{为} \{1,2,\dots,n\} \text{的划分}}(-1)^{k-1}\prod_{i=1}^{k} g_{T_i} \]

观察到实际上 \(f=1-\exp(-g)\)。这个直接卷积优化就可以了。

时间复杂度 \(O(3^n\frac{m}{\omega})\)

Source:P11714 [清华集训 2014] 主旋律

7.3 [省选联考 2024] 重塑时光

题意也太长了。简述一下,就是把 \(n\) 个数分成一些段,然后重排,段可以为空,排列后需要满足拓扑关系。

先考虑计数。

其实分段这件事有点何意味,那你就直接在状态里记上它。排列后需要满足拓扑关系,可以分成两种情况考虑:段内部点需要满足拓扑关系,段与段之间需要满足拓扑关系。把段看成一些点,这些点就会构成一个 DAG。

\(f_{S,i}\) 表示 \(S\) 中选 \(i\) 段形成的合法 DAG 数量。为了转移,我们照例再设 \(g_{S,i}\) 表示 \(S\) 中选 \(i\)\(0\) 度段构成的合法 DAG 个数。你还需要满足段内部点的合法关系,再设 \(h_{S}\) 表示 \(S\) 的合法拓扑关系数。接下来就是按所设状态设计转移:

\[f_{S,i}=\sum_{\substack{T\subseteq S}}\text{chk}(T,S\backslash T)\sum_{j=1}^{i}f_{S\backslash T,i-j}g_{T,j}(-1)^{j-1} \]

\[g_{S,i}=\sum\limits_{\substack{T\subseteq S \\ \text{lowbit}(S)\in T}}\text{chk}(T,S\backslash T)\text{chk}(S\backslash T,T)g_{S\backslash T,i-1}h_{T} \]

\[h_{S}=\sum_{u\in S}\text{chk}(S\backslash u,u)h_{S,u} \]

\(O(3^nn^2)\) 转移即可,\(O(3^nn)\) 的做法鸽了。观察到这两种做法在常数的影响下差距并不是很大。

考虑如何计算概率。对于分成 \(i\) 段的情况,首先你可以将这 \(i\) 段任意重排,然后和 \((k+1-i)\) 个空段合并,再随便切 \(k\) 刀,即 \(i!k!\binom{k+1}{i}\)。最后除以总方案数 \((n+k)!\) 即可。

Source:P10221 [省选联考 2024] 重塑时光

8 双联通性限制

8.1 数点双联通子图

给定一张无向图 G,求有多少边子图是点双联通图。

我们分阶段地考虑这个问题,设 \(f_0,f_1,\dots,f_n\)\(n\) 个集合幂级数,其中 \((f_i)_S\) 表示 \(S\) 的导出子图中,割点编号不超过 \(i\) 形成的子图数。我们想要计算的答案是不存在割点的生成子图数,那么 \((f_0)_U\) 就是答案。

考虑如何从 \(f_{i-1}\) 转移至 \(f_i\)。我们考虑 \(f_{i-1}\)\(f_i\) 之间的差异,\(f_i\)\(f_{i-1}\) 的区别就是 \(i\) 可以成为割点。对于集合 \(S\),如果 \(i\not\in S\),那么 \(i\) 不在 \(S\) 的导出子图中,它不能成为割点,所以 \(f_{i,S}=f_{i-1,S}\)

只需考虑 \(i\in S\) 时的情形,\(i\) 可以成为 \(S\) 的割点。如果将 \(i\) 删去,那么这张图会分裂成若干联通块 \(T_1,T_2,\dots,T_k\),那么 \(\{u\}\cup T_1\cup T_2\cup \dots\cup T_k=S\)。那么这张边子图在所有 \(T_i\) 的部分都符合 \(f_{i-1}\) 的限制,那么这是一个划分形式,将所有 \(i\in S\)\(f_{i-1,S}\) 去掉 \(i\) 做一遍 \(\exp\) 即可。

考虑如何计算 \((f_n)_S\),这相当于没有割点的限制,只需要对 \(S\) 导出子图中有多少子图是联通的计数。直接使用 6.1 的做法即可。

那么我们可以将 \(i\)\(n\)\(1\) 推回去,这相当于做 \(\ln\)。那么只需要做 \(O(n)\)\(\ln\) 即可,时间复杂度 \(O(n^32^n)\)

Source:P16207 点双连通生成子图计数

总结

集合幂级数在近几年出现次数比较多,是常考的热门题型,值得重视。

在研究集合幂级数时的主要思想就是将集合划分,然后对这个划分的过程递推。

对于无向图简单连通性题目,需要掌握 \(\exp\) 的组合意义,这样就从整块联通性问题就转化为了若干散块连通性问题。对于有向图连通性问题,可以考虑钦定 \(0\) 度点。一张 DAG 上总是存在零度点,而一次剥开每一层零度点就可以描述 DAG 的结构。这就能转化到集合划分的形式。

如果计数时会算重,可以对每个状态赋一个容斥系数使得每种方案恰好被我们算过 \(1\) 次,并且不符合条件的状态也不会被计入。对有向图连通性问题,对其做 DAG 容斥,这样的处理通常是有力的。

posted @ 2026-04-10 09:42  jeffreyli2025  阅读(17)  评论(0)    收藏  举报