容斥原理

入门

引入:有 \(k\) 种属性,你有一个函数 \(f(S)\),可以得知至少满足 \(S\) 属性的集合的物品个数。其中 \(f(\emptyset)=0\),求至少有一种属性的物品的个数。

容易得出,\(\sum\limits_{S \subseteq U}f(S)(-1)^{\lvert S\rvert+1}\)

如何验证?假设一个物品有 \(n\) 个属性,在 \(n=0\) 的时候,\(f(\emptyset)=0\)
如何 \(n \ge 1\),可以枚举一下哪些组合被枚举到。

\[\sum\limits_{i=1}^n\begin{pmatrix}n\\i\end{pmatrix}(-1)^{i+1}=-(\sum\limits_{i=1}^n\begin{pmatrix}n\\i\end{pmatrix}(-1)^i)=-((1-1)^n-1)=1 \]

所以对于 \(n \ge 1\) 的时候,每个物品恰好被枚举到了一次。

这种问题一般化解法,\(q(S)\) 表示可以快速得到至少满足 \(S\) 属性的物品的个数,还有一个贡献函数 \(g(k)\) 表示一个有 \(k\) 个属性的物品会对答案产生 \(g(k)\) 的贡献,本题中 \(g(0)=0\),其他 \(g(k)=1\)。同时还有容斥系数 \(f(\lvert S\rvert)\)

我们可以通过 \(g(n)\) 来计算容斥系数。

\[\sum\limits_{i=1}^n\begin{pmatrix}n\\i\end{pmatrix}f(i)=g(n) \]

可以通过递推 \(O(n^2)\) 来计算 \(f(x)\)

\[f(n+1)=g(n+1)-\sum\limits_{i=1}^n\begin{pmatrix}n+1\\i\end{pmatrix}f(i) \]

引入2:有 \(n\) 个背面朝上的硬币编号为 \(1-n\)。有 \(m\) 次操作,每次给定 \(a_i\),把所有 \(a_i\) 的倍数的硬币都翻转。求每次操作后有多少个硬币正面朝上。\(n\le 10^9,m\le 15,a_i\le 10^5\)

转化一下题意,就是问有多少个数被奇数个 \(a_i\) 整除。考虑钦定集合 \(S\) 表示有多少个数被 \(S\) 中的数整除。这个可以通过算一下 \(\mathrm{lcm}\) 来解决,这样子我们就得到了 \(q(S)\)

最后的答案就是 \(\sum\limits_{S\subset U}q(S)f(\lvert S\rvert)\)。我们需要算一下容斥系数 \(f\)

考虑贡献函数 \(g\)\(g(k)\) 表示一个能被 \(k\) 个数整除的数带来的贡献。

\[g(k)=[k \bmod 2=1]=\sum\limits_{i=0}^k\begin{pmatrix}k\\i\end{pmatrix}f(i) \]

可以 \(O(m^2)\) 递推,或者打表观察结果得出 \(f(n)=(-2)^{n-1}\)

方法总结

一般我们可以通过钦定某些合法/不合法,来快速计算某某条件合法的数量。

其实主要是求两种,画个韦恩图,一种是求中间那个小小的交集(一般情景就是要求所有东西都满足某个条件的方案数),还有一种是求全集也就是所有集合的并集(一般是求满足至少一个属性的物品个数,见第一个例子)。前者我们钦定若干个不满足这个条件的东西来求方案数,后者是钦定满足若干个属性的物品个数。

分析一下上述计算的方便之处,前者是我们可以把所有东西都满足某个性质的要求转化为某些不满足(满足条件相对难以处理,不满足条件其实好做点只需要恰好超出临界即可),而且剩下的没被钦定的就随便了没有限制。

后者就是我们可以把需要满足 \(A\) 但是又要小心同时满足了 \(A,B\) 需要去重的这种东西,转化为多次计数,其中每个单次计数中只需要单独考虑满足 \(A\) 而不需要考虑和别的重复。

钦定之后就很好做了,因为除了钦定的东西,剩下的东西就没有限制了,很好计数。

P5505 [JSOI2011] 分特产(第一类)

考虑容斥原理,设 \(f_i\) 表示钦定 \(i\) 个人没有分到特产的方案数。

现在进行 \(f_i\) 的计算,首先要选出钦定的 \(i\) 个人就是 \(n\choose i\),然后对于每一种特产都用插板法然后乘法原理计算即可。

最后答案就是 \(\sum\limits_{i=0}^{n-1}(-1)^if_i\)

P2567 [SCOI2010] 幸运数字(第二类)

很显然的容斥。我们先找到所有 \(\le r\) 的幸运数字,然后钦定集合 \(S\),用 \(q(S)\) 表示被集合 \(S\) 中的数整除的数的个数(这个可以通过算 \(\mathrm{lcm}\) 来得到)。

直接这么做的话,复杂度会爆。考虑剪枝,我们 dfs 式枚举所有数,每次搜索加/不加。当 \(\mathrm {lcm} >r\) 的时候可以直接退出,还有就是那些 \(a_i|a_j\)\(j\) 无用可以提前去掉,还有就是我们从大往下枚举 \(a_i\),这样子 \(\mathrm{lcm}\) 增长得更快。

P2167 [SDOI2009] Bill的挑战(第二类扩展版)

本题就是 引入 \(1\) 的变式。本题就是有 \(n\) 个属性,求恰好满足其中的 \(k\) 个的方案数。我们可以计算出它钦定了满足属性 \(S\) 的方案数,然后容斥一下即可。

答案就是 \(\sum\limits_{S\subset U}f(\lvert S\rvert)q(S)\)\(q(S)\) 很好求出就是钦定了 \(S\) 集合,要求满足其中的限制,我们枚举 \(T\) 的每一位,\(S\) 对每一位的限制必须是某个字母或者全是通配符(如果不是就是 \(0\) 种了),然后 \(26\) 的任意填位置个数次幂就是答案了。

\(g(n)\) 为贡献函数,可以得到 \(g(n)=[n=k]=\sum\limits_{i=0}^n{n\choose i}f(i)\)

首先可以根据上述式子发现对于 \(i<k\)\(f(i)=0\)。打个表可以发现对于 \(i\ge k\)\(f(i)=(-1)^{i-k}{i\choose k}\)。其实这个本质就是二项式反演!

错排问题

我们直接钦定 \(i\) 个位置不满足条件,钦定有 \(n\choose i\) 种方案,剩下的随便排就是 \((n-i)!\)

\[\begin{aligned}f(n)&=\sum\limits_{i=0}^{n}(-1)^i {n\choose i}(n-i)!\\ &=\sum\limits_{i=0}^n (-1)^i\dfrac{n!}{i!}\\ &=n\sum\limits_{i=0}^n (-1)^i\dfrac{(n-1)!}{i!}\\ &=(-1)^n\dfrac{n!}{n!}+n\sum\limits_{i=0}^{n-1} (-1)^i\dfrac{(n-1)!}{i!}\\ &=(-1)^n+nf(n-1) \end{aligned}\]

如果要求恰好 \(k\) 个位置满足错排呢?我们找到 \(k\) 个位置后,剩下的位置显然只能 \(p_i=i\),所以答案就是 \({n\choose k}f(k)\)

方程解的个数

\(n\) 个非负整数 \(x_i\)\(\sum x_i=m\),其中 \(l_i\le x_i\le r_i\)。求 \((x_1,x_2,...,x_n)\) 的个数。

对于下界很好处理,就是 \(x_i\gets x_i-l_i \ge 0\),同时上界也需要变化 \(r_i\gets r_i-l_i\)。转化为 \(x_i\in [0,r'_i]\)

不过对于上界的处理其实很难办,唯一的方法就是容斥原理。我们钦定一个集合 \(S\)\(x_i>r'_i\),减去这一部分大小即可。于是答案就是 \(\sum\limits_{S\subset U}(-1)^{\lvert S\rvert}{n+m-1-\sum\limits_{x\in S}(r'_i+1)\choose n-1}\)

练习题:Devu and Flowers

快速计算容斥系数

\(g(n)=\sum\limits_{i=0}^n\begin{pmatrix}n\\i\end{pmatrix}f(i)\)

可以得出,\(\dfrac{g(n)}{n!}=\sum\limits_{i=0}^n\dfrac1{(n-i)!}\dfrac{f(i)}{i!}\)

\(G(x)=\sum\limits_{i=0}^{\infty}\dfrac{g(i)}{i!}x^i\)\(H(x)=\sum\limits_{i=0}^n\dfrac{1}{i!}x^i\)\(F(x)=\sum\limits_{i=0}^{\infty}\dfrac{f(i)}{i!}x^i\)

\(G(x)=H(x)F(x)\),于是 \(F(x)=\dfrac{H(x)}{G(x)}\)。运用多项式求逆可在 \(O(n\log n)\) 的时间内求出。

进阶 Trick

图计数

  • 图联通计数:\(f_s\) 为集合 \(s\) 内联通的方案数,考虑使用容斥拿总的 \(2^{e(s)}\) 减去不合法的图。不合法的只需要钦定一个包含 \(\rm lowbit(s)\) 的联通集合,剩余的随便选就行了。可以预处理 \(e(S)\),做到 \(O(3^n)\)
  • 树计数:设 \(f_s\) 为集合 \(s\) 为一颗树的方案数,直接通过一条边把 \(S\) 分裂成两个集合 \(s,t\)\(f_S\gets f_s\times f_t\),可以发现 \(S\) 一共被计算了 \(\rm popcount(S)-1\) 次,除掉即可。

  • 二分图计数:见下方例题:ARC105F。省流版:把图联通计数中的所有 \(2^{e_s}\) 都换成 \(h_s\),其中 \(h\) 代表区分黑白意义下的不要求联通二分图数量。

P10982 Connected Graph

图计数入门题。

\(e_i\) 表示 \(i\) 个的完全图的边数 \({i\choose 2}\),设 \(f_i\) 表示 \(i\) 个点的标号联通图。

考虑使用容斥,先 \(f_i\gets 2^{e_i}\),然后再扣除不合法的方案数。不合法的方案必定是需要不联通的,不联通图可以被划分为至少两个内部联通点集(集合之间不联通),如果直接枚举的话不好确定对象,不妨把只枚举其中一个内部联通且和外部不联通的集合,这个集合确定之后,我们可以发现外面是可以任意选择的,不管外面怎么选,都能被划分为至少两个之间不联通的点集。

但是我们钦定的这个联通的点集,会在一个拥有多个联通块的图中被计算多次(每个联通块可以作为被钦定联通的集合),发现这张图中 \(1\) 号点所在联通块唯一,于是我们就强行要求包含 \(1\) 号点所有在联通块这样子就唯一了。

我们直接枚举被钦定联通的集合大小,然后组合数是分配系数,由于 \(1\) 号点已经被要求在集合中了,所有只需要从剩下的 \(i-1\) 个点中选择 \(j-1\) 个就行了。最后 \(2^{e_{i-j}}\) 代表剩余部分随便选的方案数。

\[f_i=2^{e_i}-\sum\limits_{j=1}^{i-1}f_j\times {i-1\choose j-1}\times 2^{e_{i-j}} \]

时间复杂度 \(O(n^2)\)

ZROI2945.森林

给一定张 \(n\) 个点的图,求每条边以 \(\dfrac{1}{2}\) 的概率存在的时候,这张图的最小生成树森林的权值期望。其中 \(n\le 16\)。无重边自环。

考虑按照 Kruskal 的过程来思考,我们应该从小往大加入边。显然影响某条边是否能产生贡献的因素就是比它小的边构成的图,只要比它小的边构成的图中 \(u\)\(v\) 不在同一联通块,那么边 \((u,v)\) 就能产生贡献,这需要我们对于图联通计数。

考虑 \(O(m)\) 从小到大枚举边,枚举集合 \(s\),满足只有 \(u\) 在其中,而 \(v\) 不在,贡献就是 \(f^s\times 2^{e(U/s)}\times w\)。每次加入一条边统计过答案之后做一次 \(O(3^n)\) 的图联通计数,重新计算 \(f_s\)

时间复杂度 \(O(m3^n)\)

P6789 寒妖王

考虑按照 Kruskal 的过程来思考,我们应该从大到小加入边。显然影响某条边是否能产生贡献的因素就是比它大的边构成的图。

这条边能产生贡献有以下两种情况,

  • 比它大的边构成的图中 \(u\)\(v\) 在同一联通块,且这个联通块是一棵树。

  • 比它大的边构成的图中 \(u\)\(v\) 不在同一联通块,且这两个联通块至少有一个是一棵树。

\(f_s\) 表示集合 \(s\) 内的点构成一棵树的方案数,\(g_s\) 表示集合 \(s\) 内的点构成联通块的方案数,按照上文中的计算方式进行求解即可。

第一种贡献情况可以直接用 \(f_s\) 解决。第二种情况的贡献就是 \(f_sg_t+f_tg_s-f_sf_t\)

每次加入一条边统计过答案之后就做一次 \(O(3^n)\) 的图联通计数,重新计算 \(f_s\)\(g_s\)。这里可以卡常就是我们只重新计算和 \(u,v\) 有关的 \(s\),其他的不会发生变化。

时间复杂度 \(O(m3^n)\)

ARC105F Lights Out on Connected Graph

两个约束条件:图联通和二分图。

考虑先满足第二个条件,并对于第一个条件进行容斥。

\(h_s\) 表示集合 \(s\) 为若干个二分图的方案数。对于每个集合 \(s\),我们将其划分为不相交的两个集合 \(s_1,s_2\),设两个集合之间的连边为 \(c\) 个,那么就有 \(2^c\) 种方案,代表二分图左右内部的边不可选,左右之间的边可选可不选。对于所有划分求和即可。其中 \(s_1\) 或者 \(s_2\) 可以为空集,

不过上述求出来的有点小问题,就是一个有 \(k\) 个联通块的图会被计算 \(2^k\) 次。因为上述区分了黑白,一个联通块为一个二分图,可能左白右黑,也可能左黑右白是被统计了两次的。所以我们 考虑在区分黑白的意义下进行统计。

\(f_s\) 表示联通块 \(s\) 在区分黑白的意义下连成二分图的方案数。

那么根据经典图联通容斥,我们只需要用总方案数减去钦定 “最小点”所在联通块联通其他点任意的方案数即可。

最后注意需要答案除以 \(2\),因为我们上面说了在区分黑白的意义下。

时间复杂度 \(O(3^n)\)

DAG 容斥

分为两种,一种是求对于无向图边定向成 DAG 的方案数。还有一种是求 DAG 导出子图计数。

P6846 [CEOI 2019] Amusement Park

首先先转化一下,如果我们用了 \(x\) 次将其定向为了 DAG,那么可以用 \(m-x\) 次转化其反图,所以直接转化成无向图定向成 DAG 的方案数乘以 \(\dfrac{m}{2}\)

需要每次剥离一个独立集,这样子去掉之后还是一个 DAG,就可以 dp 一层一层来解决。按理来说每次必须剥离干净,但是这样子太难转移了,所以只能容斥,系数是 \((-1)^{|T|+1}\)

\[f_{S\cup T}\gets f_S(-1)^{\lvert T\rvert+1} \]

其中 \(T\) 是一个独立集。思考这个系数为何正确,上面说了在一次直接剥离干净的时候直接去掉是正确的,设这个需要被剥离干净的集合为 \(U\),我们枚举的 \(T\),都是其非空子集,我们需要 \(\sum\limits_{T\subset U}f(|T|)=1\)。对于 \(U\) 其大小为奇偶的子集是一样的,由于我们不考虑空集,所以奇子集比偶子集多 \(1\),于是奇数子集产生 \(1\) 的贡献,偶数集合产生 \(-1\) 的贡献就行了。

时间复杂度 \(O(3^n+m2^n)\)

ABC306Ex Balance Scale

假设没有 '=' 的时候,就是一个 DAG 定向了。

需要每次剥离一个独立集,这样子去掉之后还是一个 DAG,就可以 dp 一层一层来解决。按理来说每次必须剥离干净,但是这样子太难转移了,所以只能容斥,系数是 \((-1)^{|T|+1}\)

\[f_{S\cup T}\gets f_S(-1)^{\lvert T\rvert+1} \]

其中 \(T\) 是一个独立集。思考这个系数为何正确,上面说了在一次直接剥离干净的时候直接去掉就行了,但是我们无法一次就剥开,设这个需要被剥离干净的集合为 \(U\),我们枚举的 \(T\),都是其非空子集,我们需要 \(\sum\limits_{T\subset U}f(|T|)=1\)。对于 \(U\) 其大小为奇偶的子集是一样的,由于我们不考虑空集,所以奇子集比偶子集多 \(1\),于是奇数子集产生 \(1\) 的贡献,偶数集合产生 \(-1\) 的贡献就行了。

有 '=' 的时候就是相当于将相邻 "=" 点也就是一个联通块缩成一个点,这样子我们就不要求加入独立集了,加入的点集中有若干联通块,对于单个联通块看成缩成一个点,于是原本系数中的点集大小 \(|T|\) 变成了联通块数。也就是联通块数 \(+1\) 就行了。

DAG子图计数

\[f_s=\sum\limits_{T\subset S,T\neq \emptyset}(-1)^{|T|+1}f_{S/T}2^{\rm way(T,S/T)} \]

注意这次不需要枚举独立集了,因为是子图,内部的边可以不选。

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

首先总的方案数为 \(n!\prod\limits_{i=1}^k(n+i)\),把这个作为分母,将求概率转化为求方案。

精简题目之后,我们将 \(\{1,2\dots n\}\) 的划分成若干集合,集合之间无序但是要求存在一种排列方式使得这些集合可以满足题目给定的 DAG 形态,集合内部按照给定 DAG 形态有序。

设我们最后划分出来了 \(i\) 个小集合,由于题目是对于排列划分且划分算上顺序,所以有一个 \(i!k!\) 的系数,同时还有 \(k-i\) 个空段要插进去,容易用隔板法算出这是 \(k+1\choose i\) 种方案。

将一堆额外系数算完之后,我们现在就只需要解决精简之后的题意了。

由于集合内部是有序的,所以我们需要算出合法排列数量,也就是子图拓扑序计数。设 \(h_s\) 表示集合 \(s\) 的拓扑序个数,转移就是加入一个点 \(\{u\}\),满足没有 \(u\to S\) 的边即可,

\[h_{S\cup \{u\}}\gets [to_u\cap S=\emptyset ]h_S \]

上面算出了集合内部的系数,现在要求的是划分集合的方案数。考虑将整个集合看出一个大点,我们要对于这张大点的 DAG 进行计数。使用 DAG 计数常用手段,每次剥离一个独立集 \(T\),系数是 \((-1)^{|T|+1}\)

需要注意的是,由于我们需要关注非空集合的数量,所以在 DP 计算的时候必须带上集合的个数,所以要多开一个维度。设 \(f_{i,S}\) 表示划分了 \(i\) 个大集合,用了 \(S\) 这些点的方案数。

每次剥离独立集的时候也要枚举独立集 \(T\) 的大小 \(j\),注意这里 \(j\neq |T|\),因为 \(T\) 记录的是用了哪些小点,而 \(j\) 表示的是当前 DAG 上用的大点个数。然后从 \((-1)^{j+1}f_{i-j,S-T}\) 转移而来,这里还少一部份方案数的系数 \(g_{j,T}\)

\(g_{j,T}\) 就是要用 \(T\) 中的点组合成为 \(j\) 个的大点,要求这些大点之间互相没有连边,按照以下式子转移即可,限制 \({\rm lowbit}\) 是为了防止重复计算。

\[g_{i,S}=\sum\limits_{T\subseteq S,{\rm lowbit}(S)={\rm lowbit}(T)}[to_T\cap(S-T)=\emptyset][to_{S-T}\cap T=\emptyset]h_{T}g_{i-1,S-T} \]

求出 \(g\),之后就可以转移 \(f\) 了。

\[f_{i,S}=\sum\limits_{j=1}^i\sum\limits_{T\subseteq S}[to_S\cap T=\emptyset](-1)^{j+1}f_{i-j,S-T}g_{j,T} \]

时间复杂度 \(O(n^23^n)\)

点减边容斥

联通块数 = 点数 \(-\) 边数。分开来单独求,我们求出每个点满足条件的方案数,再对于所有点求和。再求出每条边满足条件的方案数,再对于所有边求和。那第一个求和的结果减去第二个结果就是满足条件的联通块数量。

由于需要对于每个点,每条边单独求,所以一般会采用换根 dp 或者一些奇怪的技巧来去掉一个 \(n\) 的复杂度。

这个的应用很广,不一定是一个什么图形态的,可能在线性序列上有一些连续段关系之类的也可以使用。

XYD19495.热异常/牛客 Haitang and diameter

给定一颗树,边权为 \(0/1\),要求对于 \(2^{n-1}\) 种所有赋权情况求直径条数之和。\(n\le 2000\)

统计直径条数肯定能想到在直径中点处统计,但是由于本题边权可能为 \(0\),所以会有多个中点,观察到多个中点形成了一个联通块,所以直接用点减边容斥就可以将贡献变成 \(1\) 了。此时每条边贡献为 \(-1\),点贡献为 \(1\)

但是考虑当边权为 \(1\) 的时候,这边为直径中点的时候会产生 \(1\) 的贡献。所以这条边的 \(-1\)\(+1\) 贡献抵消,等于说边没贡献,于是直接统计点的贡献。

先考虑一个对于每个点为根都做一遍的做法,考虑设 \(f_{u,i}\) 表示 \(u\) 子树内最大深度为 \(i\) 的方案数,\(g_{u,i}\) 表示所有方案之下的点数总和。

首先是从子树向上合并的转移,我们枚举两边的深度 \(i,j\),枚举这条边的边权 \(z\in \{0,1\}\)

\[f_{u,\max(i,j+z)}\gets f_{u,i}\times f_{v,j} \]

\[\begin{cases} g_{u,i}\gets g_{u,i}\times f_{v,j} & i\ge j+z \\g_{u,j+z}\gets g_{v,j}\times f_{u,i}& j+z\ge i \end{cases}\]

注意关于 \(g\) 的两种转移是可以同时进行的。一直到根 \(u\) 的时候,需要从至少两个子树内选择出最大深度组合成直径才能保证 \(u\) 为直径中点,我们设 \(h_i\) 表示半径为 \(i\) 的方案数。

\[h_i\gets [j+z\le i]~h_i\times f_{v,j} \]

\[h_i\gets [j+z=i]g_{u,i}\gets g_{v,j} \]

注意这个过程是逐个子树动态做的,也就是 \(g_{u,i}\) 保存了之前那些子树得到的信息,和 \(g_{v,j}\) 合并。然后再用 \(g_v\) 更新 \(g_u\),这样子任意两个子树都能产生贡献。直接这么做是枚举根 \(+\) 树上背包 \(O(n^3)\) 的。

考虑换根,经典前后缀积优化,可以进行转移。本来 \(sz_u\times sz_v\) 的复杂度在树形背包上就是对的,但是由于本题需要统计答案,统计答案就是把周围子树进行一个卷积卷起来,这样子对于每个点都卷周围一圈复杂度就不对了,因为卷周围一圈的时候,不仅会卷积子树,还会卷到子树外面的部分。最坏单次会达到 \(O(n^2)\) 的。

但是观察上述转移式子的时候,发现转移条件都是某个数大于另一个数,所以可以用前后缀和优化转移,把单次的复杂度做到 \(\max(sz_u,sz_v)\) 这样子就正确了。时间复杂度 \(O(n^2)\)

P10064 [SNOI2024] 公交线路

考虑如何判定,对于每个点 \(u\) 求出可以一步到达的所有点集合 \(S_u\),那么要求对于 \(\forall (u,v)~S_u\bigcap S_v\neq \emptyset\),最紧的限制条件是叶子,所以可以将上述判定点的类型设置为叶子。

注意到这是一颗树,且任意两个叶子所对应的联通块之间交集非空,可以推广为所有叶子的交集是一个联通块。

对于联通块计数,可以用点减边容斥。求出每个点合法的方案数之和,减去每条边合法的方案数之和。

直接做的话,在遇到一条路径两个端点都是叶子的时候不好处理,于是再次容斥。钦定不经过若干叶子。对于单点是 \(O(n^2)\) 的。全局 \(O(n^3)\)

每次扔掉一个子树,就可以做到树上背包的复杂度。

QOJ9840.Tree Partition

直接进行树上背包,显然复杂度太高且无法刻画联通块编号连续这个信息。

考虑转化一下,我们在值域上进行这个 dp,每次提取一个值域连续段,要求其在树上构成一个联通块。对于一个点集,可以通过点减边为一来判定其为一个联通块。于是我们直接 dp,利用线段树维护转移点到目前点构成区间的点减边数量,同时注意到点减边最少也得是 \(1\),于是我们就直接记录最小值位置的 dp 值之和,进行转移即可,时间复杂度 \(O(nk\log n)\)

发掘一些性质,我们给树定向,从儿子指向父亲。放到值域上,就是若干前向边和后向边。发现最多可以"浪费一条边"(向区间外部连),也就是这个联通块的根向父亲的边,其余的边必须在这个区间内部。

于是我们可以得到判定条件就是,扫描到 \(i\) 的时候,对于 \(fa_j>i\)\(j\) 最近和次近的 \(j\) 分别为 \(x,y\)。那么 \(j\in [y,x)\) 能转移到 \(i\) 的条件为 \([j,i]\) 没有连到 \([1,j)\) 的边。这是对于后向边区间的判定条件。对于前向边区间类似判断即可,可以先 \(O(n\log n)\) 用数据结构维护出来转移点,然后再 dp 一遍 \(O(nk)\) 解决。

内外向树的拓扑序容斥/不等关系容斥

  • 前置知识:\(n\) 个点外向树拓扑序个数为 \(\dfrac{n!}{\prod sz_i}\)

其中每个子树贡献了 \(\dfrac{1}{sz_i}\),一般是对于这个贡献进行容斥。\(n!\) 最后乘就行了。

P12639 [UOI 2020] Topological Sorting of a Tree

将填入数字看成拓扑序,如果全部都是 \(<\) 的话很好办,那就是外向树拓扑序个数,为 \(\dfrac{n!}{\prod size_u}\)

现在我们多了内向边,于是需要把他们容斥掉。假设钦定了 \(c\) 条符号为 \(>\) 的边不满足性质(变成了 \(<\) 号的边),那么就有 \((-1)^c\) 的系数。这样子最后会形成一个森林,一颗树的内部有拓扑序要求,树和树之间无要求。合并两颗大小分别为 \(n\)\(m\) 的树的方案数为将排名 \([1,2\dots n]\) 和排名 \([1,2\dots m]\) 整合到排名 \([1,2\dots n+m]\) 的方案数,你只需要在这 \(n+m\) 个位置中选 \(n\) 个位置依次填入原排名为 \(1,2\dots n\) 的数即可,那么就是 \({n+m\choose n}\)

考虑带着容斥系数进行 dp,每钦定一条边就 \(\times (-1)\)

由于贡献系数是和子树大小相关的,所以我们要在 dp 的时候记录当前联通块的大小。所有设 \(f_{u,i}\) 表示在 \(u\) 点的时候其所在联通块大小为 \(i\) 的时候的带着容斥系数的方案数之和。根据拓扑序公式,每次遇到一个大小为 \(i\) 的子树都要乘上 \(\dfrac{1}{i}\) 的贡献,这个我们放在最后乘,下面的转移式子中不讨论这一项

在遇到 \(<\) 的时候,就是 \(\dfrac{n!}{\prod sz_i}\)\(\dfrac{m!}{\prod sz_i}\) 变成 \(\dfrac{(n+m)!}{\prod sz_i}\),我们发现这个变化恰好是 \(\dfrac{(n+m)!}{n!\times m!}={n+m\choose n}\)

\[f_{u,i+j}\gets f_{u,i}\times f_{v,j}\times {sz_u+sz_v\choose sz_u} \]

在遇到 \(>\) 的时候,可以选择不钦定那么就是任意顺序,是森林的合并,有系数 \({sz_u+sz_v\choose sz_u}\),或者钦定为 \(<\),和第一个转移系数相同就是多了一个 \(-1\)

\[f_{u,i+j}\gets -f_{u,i}\times f_{v,j}\times {sz_u+sz_v\choose sz_u} \]

\[f_{u,i}\gets f_{u,i}\times f_{v,j}\times {sz_u+sz_v\choose sz_u} \]

注意每次做完转移之后要 \(f_{u,i}\gets f_{u,i}\times \dfrac{1}{i}\)

时间复杂度 \(O(n^2)\)

QOJ8047. DFS Order 4

由于可能多颗树能得到相同的 dfs 序,所以我们可以来考虑有多少种 dfs 序可以还原到一颗合法的树。需要判定序列合法性。

如何判定一个序列合法?我们贪心的把点往一条父链上挂。如果 \(p_i>p_{i-1}\),那么可以挂在这条链末尾 \(p_{i-1}\) 的下方。如果 \(p_i>p_{i-1}\),我们可以在这条链上找到一个最浅的祖先满足 \(p_k<p_i\),我们把 \(p_i\) 挂在 \(p_k\) 的父亲上(这相当于 dfs 的回溯过程),这样子既满足兄弟节点编号递增,也满足了儿子大于父亲。这样子排列就和树一一对应了。

这样子贪心连出来的树等价于以下限制:每个点编号大于父亲,每个点儿子编号单调递增,且小于上一个兄弟的最后一个儿子。

可以发现第 \(2\)\(k\) 个兄弟节点和父亲间的约束没有用,可以通过 \(son_2>son_1>fa\) 来得到。直接删掉就行了,只有在兄弟之间连边。

有一个结论就是一颗外向图的拓扑序个数是 \(\dfrac{n!}{\prod sz_i}\)。但是本题由于有了小于上一个兄弟的最后一个儿子这个限制,导致这不是一颗外向树。

考虑容斥掉这条边,也就是 \([u<v]=1-[u>v]\)。等号右边的两种情况都是一棵树,第一种情况系数是 \(+1\),第二种情况系数是 \(-1\)

现在需要分析一下新构建的外向树长什么样子。从父子关系角度考虑,有如下三种:一个父亲和它的第一个儿子,相邻兄弟,上一个兄弟的最后一个儿子和这个点。

现在考虑在一层兄弟链上面考虑,其中不止有第二类边,还有第三类边,也就是中间会夹杂着若干个上一个兄弟的一堆儿子。在链上如果走到了下方的节点,根据上述边分类,可以发现这是属于 \(-[u>v]\) 这种边的需要乘上一个 \(-1\) 的系数。

\(d_i\) 表示 \(sz=i\) 的子树的贡献,在链上挂子树的时候算贡献。\(f_{i,k}\) 表示 \(sz=i\),在链上深度走到了 \(k\) 的方案数。

首先有 \(f_{i,0}=g_i\)

合并子树,\(f_{i+j,k}\gets f_{i,k}\times d_j\times\dfrac{j}{i+j}\)

往下走,\(f_{i+j,k+1}\gets -d_j\times f_{i,k}\times\dfrac{j}{i+j}\)

往上走,\(f_{i+1,k-1}\gets f_{i,k}\times \dfrac{1}{i+1}\)

直接在一条链上往上连一个点,\(d_{i+1}\gets f_{i,0}\times\dfrac{1}{i+1}\)

注意一下细节,我们是按照 \(sz\) 从小往大处理,所以有些 \(f_{i,k}\times d_j\)\(d_j\)\(i\) 处还没有被算到,需要在 \(j\) 处再处理一下。

答案就是 \(d_n\)。时间复杂度 \(O(n^3)\)

反射容斥

相比于卡特兰数的格路行走,这次的要求是不能经过 \(y=x+a\)\(y=x-b\) 两条线。

考虑交替碰到两条线的序列,ABABAB...,BABABA... 和空串。前两者产生 \(0\) 的贡献,后者产生 \(1\) 的贡献。

对于经过 \(A\) 或者 \(B\) 的单条线进行容斥,会多扣除经过 \(AB\) 和 经过 \(BA\) 的方案,加回来经过 \(AB\) 和经过 \(BA\) 的方案,又会多加上经过 \(ABA\) 和经过 \(BAB\) 的方案......

\(AB\) 相交的方案数,就是以 \(A\) 为对称轴翻折终点和线 \(B\),再以翻折过后的 \(B'\) 为对称轴再次对称得到最后的终点。其他 AB 组合也是以此类推。

按照上述做法进行容斥,答案就是 \(\sum\limits_{k\in Z}{n+m\choose n-k(a+b)}-\sum\limits_{k\in Z}{n+m\choose n-k(a+b)+a}\)

注意上述 \(k\) 可以取到负数,而且前后两个式子 \(k\) 的范围是不同的。

可以 \(O(n)\) 预处理,\(O(\dfrac{n}{a+b})\) 进行单组回答。

gym104053J. Math Exam

给定一个长度为 \(n\),值域在 \(\{-1,1\}\) 之间的序列,求任意前缀和在 \([0,m]\) 之间的方案数。

转化一下就是要求行走过程中始终满足 \(x-m\le y\le x\),我们枚举最后的终点共计 \(m\) 个,单次求解复杂度 \(O(\dfrac{n}{m})\),总复杂度就是 \(O(\dfrac{n}{m}\times m)=O(n)\)

杂题

ABC294Ex K-Coloring

很显然的容斥,考虑钦定一个边集 \(S\) 使得其不满足要求,用 dfs 一下联通块数目,假设只连这些边形成了 \(c\) 个联通块,那么贡献是 \(K^c \times (-1)^{\lvert S\rvert}\)。这样子的复杂度是 \(O(2^m(n+m))\)

似乎不太方便直接优化,我们发现当 \(c\) 不变的时候,\(\lvert S\rvert\) 相差一的时候会相互抵消。也就是说如果在当前集合 \(S\) 基础上我们加入一条边,而这条边对于图的联通性没有改变的话,以 \(S\) 为基础的所有包含这条边的集合和不包含这条边的集合都会抵消,那么贡献为 \(0\)

考虑用并查集维护联通性。并且 dfs (可以剪枝,枚举量不满)代替枚举。如果有并查集内已联通的边就直接返回 \(0\) 了。

为了更随机点,我们可以打乱初始边集然后开始 dfs。

P1450 [HAOI2008] 硬币购物

很巧妙的背包题,我们先进行一遍完全背包算一下没有任何限制的方案数。

考虑对于其中某一种物品进行限制,我们要减去这种物品 \(i\) 取了 \(>d_i\) 次的方案,这一部分就是强制选 \(d_i+1\) 个物品 \(i\),然后剩下的空间给四种物品随便选,也就是要减去 \(f_{tot-c_i\times (d_i+1)}\)。如果推广到多个物品呢,直接上容斥原理即可。

ZROI2943.水题 Pro Max

长度为 \(n\) 的序列,值域在 \([1,m]\) 之间,求众数出现次数的期望。

考虑计算出 \(ans_i\) 表示众数出现恰好 \(k\) 次的方案数。然后 \(\sum ans_i\times i\) 就是答案了。

对于这种最大值恰好为某个值的求解,我们都可以转化为 \([=k]=[\le k]-[\le k-1]\) 来求解。

现在问题就转化为如何快速求,所有数出现次数都 \(\le k\) 的方案数。可以容斥原理,我们钦定若干个数出现次数 \(>k\),我们设 \(f_{i,j}\) 表示当前已经按顺序填入了 \(i\) 个数中我们钦定了 \(j\) 个数的方案数。那么 \([\le k]=\sum\limits_{i=0}^n(-1)^if_{n,i}\)

加入一个数,注意需要从为被钦定的里面选:\(f_{i,j}\gets f_{i-1,j}\times (m-j)\)

钦定一个数:\(f_{i,j}\gets f_{i-k-1,j}\times (m-j+1)\times {n-i+k\choose k}\)

钦定一个数的时候需要加入 \(k+1\) 个这个数,其中第一个的位置已经确定就是按照顺序填的下一个,那么我们只需要为后面 \(k\) 个分配一下位置就行了,还剩 \(n-i+k\) 个位置,分给 \(k\) 个数,直接上组合数就行了。

AH省集 D3T1 吟游诗人

给定 \(n\) 个数 \(a_i\),和 \(m\) 个数 \(b_i\),对于每个 \(b_i\) 找到一个不同\(a_j\) 与之匹配,要求 \(b_i\mid a_j\),求方案数。其中 \(a_i,b_i,n\le 10^6\)\(m\le 17\)

直接考虑对于取值相同的 \(b\) 的集合进行容斥是不好做的,感觉不太好把多个集合放在一起做。于是使用图论建模,把匹配到相同 \(a\)\(b\) 之间连边。

一个联通块内钦定是取相同的 \(a\),于是只需要计算其 \(\rm lcm\) 即可,容斥系数是联通块边个数的 \(-1\) 次幂。这样子我们就得到了一个关于边数为指数级的算法。

直接对于便边做容斥复杂度太高,考虑对于点做容斥。在对于点容斥的时候考虑单次加入一个联通块,一个联通块的贡献通过 \(\rm lcm\) 计算,现在需要计算容斥系数,需要看看有哪些边的连接方式可以使得这些点构成一个联通块,对于每种连接方式贡献 \((-1)^k\)\(k\) 是这种连接方式中选择的边数。于是我们就只需要算出 \(g_i\) 表示在 \(i\) 个点的完全图上取 \(x\) 条边使得图联通的 \((-1)^x\) 之和。直接打表就可以得到系数是 \((-1)^{n+1}(n-1)!\),或者通过图联通容斥 dp 应该也是可以求解系数的。

最后的对于点的 dp 就很好写了,每次选取一个包含 \(\rm lowbit(s)\) 的集合作为联通块加入。

CF1553I Stairs

可以根据 \(a\) 数组将 \(p\) 划分成 \(m\) 个段,每个段内都是连续上升或者连续下降的。

有一个很直观的式子就是 \(2^mm!\),可是随意放置会导致有些段出现接起来的情况,所以算多了。

考虑弱化版,也就是阶梯必须是升序的,我们可以用容斥,钦定若干个段连起来,最后用 \(m'~!\) 来计算。如果加上降序情况,可以发现一个升序和降序的是不能接在一起的,只有单调性相同的可以拼接,同时注意长度为 \(1\) 的阶梯具有升序和降序的两个性质。假设最后有 \(A\) 个长度 \(>1\) 的,\(B\) 个长度为 \(1\) 的,那么方案数就是 \(2^A(A+B)!\)

有了上述观察,就可以先 dp 一下了,设 \(dp_{i,j}\) 表示考虑了前 \(i\) 个段,目前得到了 \(j\) 个连续段。当 \(b_i=1\)\(i-1=k\) 的时候,\(dp_{i,j}=dp_{i-1,j-1}\),否则有 \(dp_{i,j}=dp_{k,j-1}\times 2\)。最后的答案就是 \(\sum\limits_{i=1}^m(-1)^{m-i}i!dp_{m,i}\)。暴力做是 \(O(n^2)\) 的。

考虑分治,设 \(f_{i,0/1,0/1}\) 表示当前划分了 \(i\) 个连续段,最左的/最右的是否长度为 \(1\)。合并左右两个区间的时候可以发现这是一个卷积形式,直接使用 NTT 即可。时间复杂度 \(O(n\log^2 n)\),由于单次要合并 \(4\times 4\) 个 dp 数组,所以常数很大。

P11458 [USACO24DEC] All Pairs Similarity P

如果只有分子的话,就是对于每一位拆贡献就行了。

推广到有分母的情况,还是拆分子贡献,枚举分子每一位把该位置有 \(1\) 的分母放在一起处理。

于是对于分母,我们只需要算出 \(\dfrac{1}{\vert a_i\cup a_j \vert}\) 的贡献就行了,因为对于分子我们已经拆掉贡献了(其实这一步是可以通过 \(\vert a_i\cap a_j\vert=\vert a_i\vert+\vert a_j\vert-\vert a_i\cup a_j\vert\) 直接去掉分母的,不过未必能注意到)。

先是做一步转化,将 \(a_i\) 按位取反,那么贡献也发生了变化 \(\dfrac{1}{\vert a_i\cup a_j \vert}\to \dfrac{1}{k-|a_i\cap a_j|}\),考虑 \(j\to i\) 的贡献,可以发现 \(a_i\cap a_j\)\(a_i\) 的子集,也是 \(a_j\) 的子集。所以贡献法的流程应该是 \(a_j\) 贡献给自己的所有子集,\(a_i\) 再从自己所有的子集中求和。

不过这么做肯定会算重的,具体来说 \(\sum\limits_{s\subset a_i\cap a_j} \dfrac{1}{k-|s|}\) 被我们计算了多次。而我们只希望其贡献出 \(\dfrac{1}{|a_i\cap a_j|}\)。因此设计出一个容斥系数 \(f(|s|)\) 和贡献函数 \(g(|t|)=\dfrac{1}{k-|t|}\),我们希望 \(\sum\limits_{s\subset t}f(|s|)=g(|t|)\),也就是说 \(\sum\limits_{j=0}^i{i\choose j}f_j=g_i\)\(k\) 很小,所以这个式子是可以 \(O(k^2)\) 递推的。

于是我们只需要对于 \(a_j\) 的所有子集 \(s\) 都加上 \(f(|s|)\),再对于 \(a_i\) 的所有子集求和即可。

对于前者就是对于超集做一遍高维前缀和,后者就是对于子集做一遍高维前缀和。问题就做完了。

时间复杂度 \(O(nk+k^22^k)\)

LOJ575 不等关系

考虑只有 \(<\)\(?\)的时候的做法,直接就是集合划分了,也就是 \(\dfrac{(n+1)!}{\prod len_i!}\)

于是直接把大于号容斥掉就行了,替换成 \([?]-[<]\),每次替换成 \(?\) 有一个 \(-1\) 的系数。

考虑带着容斥系数 dp,\(n!\) 最后乘,中间记录 \(\dfrac{1}{len!}\) 的贡献即可。记录一下连续段的长度就可以做了,我们设 \(dp_{i,j}\) 表示考虑了前 \(i\) 个位置,当前 \(<\) 连续段的长度为 \(j\)。如果 \(<\) 的时候,直接在之前的连续段后加上一个数,\(dp_{i,j}\gets dp_{i-1,j-1}\times \dfrac{1}{j}\)。遇到 \(>\) 的时候,我们有两个选择,一个是替换成 \(?\),那么有 \(dp_{i,1}\gets \sum\limits_{j} dp_{i-1,j}\);另一种选择是替换成 \(<\),需要乘上 \(-1\) 的系数,\(dp_{i,j}\gets -dp_{i-1,j-1}\times \dfrac{1}{j}\)

暴力 dp 是 \(O(n^2)\) 的。有第二个维度的存在好像不太好优化,索性直接抛弃掉第二个维度,每次选择极长 \(<\) 段转移,内部钦定了几个 \(>\) 变成 \(<\) 号,就乘以对应的 \(-1\) 次幂。

\[dp_{i}=\sum\limits_{s_j='>'} dp_{j}\times \dfrac{1}{(i-j)!}\times (-1)^{cnt_{i-1}-cnt_j} \]

可以发现这是一个分治 NTT 的形式,可以做到 \(O(n\log^2 n)\)

P8340 [AHOI2022] 山河重整

约束条件是 \(\forall k\),对于 \(\le k\) 的数,能凑数 \([1,k]\) 之内的所有数。

\(O(n^2)\) 是很好做的,直接设 \(dp_{i,j}\) 表示用前 \(i\) 个数,凑出了和 \([1,j]\) 的方案数,直接刷表法转移就行了,注意转移的时候需要满足 \(j\ge i\)

直接优化这个 dp 很难做,于是考虑用容斥扔掉若干限制条件。我们先去掉 \(j\ge i\) 的约束,于是直接设 \(f_i\) 表示前 \(i\) 个数满足条件且和恰好为 \(i\) 的方案数。这样子答案就是 \(2^n-f_i\times 2^{n-i-1}\),每个不合法方案会在第一次不合法的时候被删掉。

对于 \(f\) 的转移,还是类似的思想,设 \(g_i\) 表示不需要满足条件单纯用 \([1,i]\) 中的若干个数凑成 \(i\) 的方案数。那么有,\(f_i=g_i-\sum f_j\times val(j,i)\),其中 \(val(j,i)\) 表示用 \([j+2,i]\) 中的数凑出 \(i-j\) 的方案数。

对于 \(g\) 的转移是由于和为 \(n\) 的若干个不同的数最多有 \(O(\sqrt n)\) 个。将整个图画成阶梯状之后做一个完全背包即可,注意选择的数不重复,所有转移约束。

对于 \(val(j,i)\times f_j\) 的转移还是类似于 \(g\) 的,首先贡献不是 \(1\),而是 \(f_j\) 了,而且我们需要加上 \(\ge j+2\) 的基础部分,也就是 \((j+2)\times i\),由于是凑成 \(i-j\),所以还需要手动 \(+j\),那就是 \((j+2)\times i+j\)

注意这个 \(f\) 转移是半在线的,采用倍增优化转移就行了。复杂度是 \(O(\sum \dfrac{n\sqrt n}{2^i})=O(n\sqrt n)\) 的。

子集反演

\(f(S)=\sum\limits_{T \subseteq S}g(T) \Leftrightarrow g(S)=\sum\limits_{T \subseteq S}(-1)^{\lvert S\rvert-\lvert T\rvert}f(T)\)

\(f(S)=\sum\limits_{S \subseteq T}g(T) \Leftrightarrow g(S)=\sum\limits_{S \subseteq T}(-1)^{\lvert S\rvert-\lvert T\rvert}f(T)\)

P3349 [ZJOI2016] 小星星

咋一看给了一张图和树好像很恐怖,其实观察到给出的图其实没啥用只是告诉我们连边约束。

于是我们直接对于那颗树进行 dp 即可。设 \(dp_{i,j,s}\) 表示映射 \(i\to j\) 中,\(i\) 子树所选择的编号集合为 \(S\)。动态加入所有儿子节点,先枚举儿子节点,然后我们枚举当前集合 \(S\),接着从补集中枚举 \(S\),从两个集合中分别枚举 \(u,v\) 的编号然后去更新两个集合的并集。时间复杂度 \(O(n^33^n)\)。可以通过一个剪枝跑过去,就是我们只枚举大小为当前 \(sz_u\) 的集合(\(sz_u\) 动态更新,每次加入一个子树就 \(sz_u\gets sz_v\)),同时另外一边只枚举大小为 \(sz_v\) 的集合,因为只有这些是有效的。

正解是考虑容斥原理。

可以发现 \(S\) 的那一维非常浪费时间,于是考虑不枚举 \(S\)

\(f(S)\) 表示恰好使用了 \(S\) 中所有点得到的答案,\(g(S)\) 表示至多只用了 \(S\) 中的点得到的答案。

显然 \(g(S)=\sum\limits_{T\subset S} f(T)\)。子集反演一下可以得到 \(f(S)=\sum\limits_{T\subset S}(-1)^{\lvert S\rvert-\lvert T\rvert}g(T)\)

二项式反演

形式一:\(f_n=\sum\limits_{i=0}^n\begin{pmatrix}n\\i\end{pmatrix}g_i\Leftrightarrow g_n=\sum\limits_{i=0}^n(-1)^{n-i}\begin{pmatrix}n\\i\end{pmatrix}f_i\)
形式二: \(f_i=\sum\limits_{j=i}^n\begin{pmatrix}j\\i\end{pmatrix}g_j \Leftrightarrow g_i=\sum\limits_{j=i}^n(-1)^{j-i}\begin{pmatrix}j\\i\end{pmatrix}f_j\)

对于形式二有组合解释,\(f_i\) 表示钦定选 \(i\) 个方案数,意思就是确定选 \(i\) 个特定的,然受剩下的随便选,由于钦定的不同所以 \(f\) 的方案有重复。\(g_i\) 表示恰好选 \(i\) 个。所以对于 \(i\ge n\)\(g_i\)\(f_n\) 中被计算了 \(\begin{pmatrix}i\\n\end{pmatrix}\) 次。

应用:我们可以通过 DP 求出钦定选择 \(i\) 个元素的方案数,然后通过二项式反演得到恰好选 \(i\) 个的方案数。

错排问题 求 \(\sum_p[\forall i,p_i \neq i]\)

\(g_n\) 表示 \(n\) 个人的错排方案数,而 \(f_n\) 表示所有排列的方案数。

枚举站错人的个数有, \(f_n=\sum\limits_{i=0}^n\begin{pmatrix}n\\i\end{pmatrix}g_i\)

反演一下可以得到,\(g_n=\sum\limits_{i=0}^n(-1)^{n-i}\dfrac{n!}{(n-i)!}\)

一维染色问题 有 \(n\) 个方格,\(k\) 种颜色,相邻格子颜色不同,每个颜色至少出现一次,求方案数。

\(g_k\) 表示出现 \(k\) 个颜色的方案数,\(f_k\) 表示 \(k\) 个颜色的总方案数。
\(f_k=k \times (k-1)^n\),并且 \(f_k=\sum\limits_{i=0}^k\begin{pmatrix}k\\i\end{pmatrix}g_i\)

反演一下,\(g_k=\sum\limits_{i=0}^k(-1)^{k-i}\begin{pmatrix}k\\i\end{pmatrix}f_i\)

二维染色问题 有 \(n\times m\) 个格子,每行每列都至少有一个格子被染色,求方案书。

\(g_{i,j}\) 表示恰好有 \(i\)\(j\) 列被涂色的方案数,\(f_{i,j}\) 表示 \(i\)\(j\) 列被涂色的方案数即 \(2^{ij}\)。有

\(f_{n,m}=\sum\limits_{i=0}^n\sum\limits_{j=0}^m\begin{pmatrix}n\\i\end{pmatrix}\begin{pmatrix}m\\j\end{pmatrix}g_{i,j}\)

反演一下,\(g_{n,m}=\sum\limits_{i=0}^n\sum\limits_{j=0}^m(-1)^{n-i+m-j}\begin{pmatrix}n\\i\end{pmatrix}\begin{pmatrix}m\\j\end{pmatrix}f_{i,j}\)

三维染色问题 有 \(n \times m\) 个格子,\(k\) 种颜色,每行和每列至少一个格子被涂色,每个颜色至少出现一次,格子可不被涂色,求方案数。

\(f_{n,m,k}=\sum\limits_{i=0}^n\sum\limits_{j=0}^m\sum\limits_{p=0}^k\begin{pmatrix}n\\i\end{pmatrix}\begin{pmatrix}m\\j\end{pmatrix}\begin{pmatrix}k\\p\end{pmatrix}g_{i,j,p}\)

反演一下,\(g_{n,m,k}=\sum\limits_{i=0}^n\sum\limits_{j=0}^m\sum\limits_{p=0}^k(-1)^{n-i+m-j+k-p}\begin{pmatrix}n\\i\end{pmatrix}\begin{pmatrix}m\\j\end{pmatrix}\begin{pmatrix}k\\p\end{pmatrix}f_{i,j,p}\)

子集反演与二项式反演区别

一般子集反演都是要求出一个具体集合值函数 \(f(s)\),通过至多恰好来转化。

而二项式反演只关心集合大小,方便求出一个关于集合大小的函数 \(f(k)\)

也就是说在子集反演中我们需要不同情况不同对待所以要集合表示法,也就是指数级的了。而在二项式反演中由于物品具有一些对称性使得我们只需要关注集合大小即可。

Min-Max 容斥

\[\max\limits_{i\in S}x_i=\sum\limits_{T\subset S}(-1)^{|T|-1}\min\limits_{j\in T} x_j \]

\[\min\limits_{i\in S}x_i=\sum\limits_{T\subset S}(-1)^{|T|-1}\max\limits_{j\in T} x_j \]

最大的作用是计算期望的时候根据期望的线性性可以直接拆开,计算每个小集合的内部的期望然后再累加。

扩展 kmax 形式

\[\mathrm{kthmax}_{i\in S} x_i=\sum_{T\subseteq S(|T|\geq k)}(-1)^{|T|-k}\dbinom {|T|-1}{k-1}\min_{j\in T} x_j \]

例题

posted @ 2024-12-04 12:26  Mirasycle  阅读(226)  评论(2)    收藏  举报