Loading

【2】容斥与二项式反演

【2】容斥与二项式反演

1.1 容斥原理

容斥原理基于的是下面的恒等式:

\[\sum\limits_{i=0}^n\dbinom{n}{i}(-1)^i=0^n=[n=0] \]

这个式子有什么意义呢?我们考虑一个长度为 \(N\) 的序列,并且要求其中每个元素都满足某个限制,计算满足这个条件的序列数量。

每个元素都满足限制 \(\Leftrightarrow\) 不满足限制的元素个数为 \(0\)

那么容斥原理告诉我们的是,满足上述限制的序列个数等于:我们钦定若干元素 不满足限制,剩下的元素任意,如果钦定的元素个数是 \(t\),那么就用这样的方案数乘上 \((-1)^t\) 求和。

我们考虑为什么是对的?

我们记 \(n\) 为不满足条件的元素个数, 那么当 \(n>0\) 时,我们会对其每个子集做一遍钦定,那么总的被算的次数就是 \(\sum\limits_{i=0}^n\dbinom{n}{i}(-1)^i=0\),也就是说对答案的贡献被抵消了!

同样的,当 \(n=0\) 时,恰好会被算一次,那么我们就只计算了 \(n=0\) 也就是所有元素都满足限制的序列个数。

这样做有什么好处呢?我们做容斥之后,元素分成了两类,被钦定不满足限制的和任意的,通常不满足限制的元素一定满足一些性质,而任意的自然不用管,于是就可以转化问题。

在很多时候,我们并不需要真的枚举子集,可以考虑一个 \(dp_{i,j}\) 表示考虑了前 \(i\) 个元素,已经钦定了 \(j\) 个的方案数,最后乘上 \((-1)^j\) 求和。

但这真的最优吗?我们考虑去掉 \(j\) 这一维,每次如果加入一个被钦定元素就给 \(dp\) 值乘上 \(-1\),这样恰好被乘了 \(j\) 次,因此我们这个容斥并不会增加复杂度!

例一P1595 信封问题

计算有多少个排列 \(p_i\) 满足 \(p_i\neq i\)

我们套用上面的分析模式,钦定若干元素不满足限制,也就是 \(p_i=i\),剩下的任意,也就是全排。

那么我们假设钦定了 \(j\) 个元素,那么一共有 \(\dbinom{n}{j}\) 个子集,剩下的就是 \((n-j)!\),不要忘了乘上 \((-1)^j\)

答案就是 \(\sum\limits_{j=0}^n(-1)^{j}\dbinom{n}{j}(n-j)!\)

例二[JSOI2011] 分特产

还是一样,钦定若干人分不到特产,剩下的随意,假设还剩下 \(n-i\) 个人,那么对于一个有 \(a_j\) 个的物品,方案数就是插板法 \(\dbinom{a_j+n-i-1}{n-i-1}\)

复杂度 \(\Theta(nm)\)

例三 P3301 [SDOI2013] 方程

假如只有 \(x_{i}\geq a_i\) 的限制,我们是可以 \(\Theta(1)\) 算的,令 \(y_i=x_i-a_i\),那么就变成:

\(y_i\geq 0,\sum y_i=m-\sum a_i\),可以直接插板。

现在还有 \(x_i\leq a_i\) 的限制怎么办?钦定若干 \(x_i\) 不满足,也就是 \(\geq a_i+1\),那么就变成了前者。

复杂度 \(\Theta(n12^{n1})\),但是傻逼出题人强迫你写 exlucas。

例三(2)HAOI2008 硬币购物

和上面基本一样,只是换成了完全背包。

例四:

计算有多少个序列 \(a\),满足 \(a_i\in [1,m],a_{i}\neq a_{i+1}\)

直接用组合的角度考虑,第一个数有 \(m\) 种,后面每个都有 \(m-1\) 种,一共有 \(m(m-1)^{n-1}\) 种。

那从容斥的角度呢?

我们这次不对点容斥,而是钦定若干个 \((i,i+1)\),也就是钦定若干 \(a_{i}=a_{i+1}\)

考虑 dp,\(f_i\) 表示考虑了前 \(i\) 个时的 dp 数组,我们考虑 \((i-1,i)\) 是否钦定:

  • 如果不钦定,那么 \(i\) 就可以任意选 \(f_i=f_i+mf_{i-1}\)
  • 如果钦定,那么 \(i\) 就只有一种选法,带上容斥系数就是 \(f_i=f_i+(-1)f_{i-1}\)

这个 dp 有点蠢啊,我们可以发现钦定的点形成了若干个区间,每个区间内是相等的,并且假如我们钦定了 \(i\) 条边,那么就形成了 \(n-i\) 个区间,一共有 \((-1)^{i}m^{n-i}\) 的贡献。

那么答案就是 \(\sum\limits_{i=0}^{n-1}\dbinom{n-1}{i}(-1)^im^{n-i}=m(m-1)^{n-1}\),得到了同样的结果。

我们接下来会说明这个 dp 和这个组合数都比一开始的做法更具拓展性。

例四的拓展

计算有多少个序列 \(a\),满足 \(a_i\in [1,m],a_{i}\neq a_{i+1}\),且 \(a_i\leq r_i\)

此时每个数有了上界的限制,我们不能直接 \(\Theta(1)\) 算了。

还是考虑上边那个容斥的思路,同样的还是每个被钦定的边构成了若干个区间,每个区间内是相等的,那么这些数一共有 \(\min_{i=L}^Rr_i\) 种选法。

还是考虑那个 dp,此时我们暴力枚举当前点 \(i\) 所属区间的左端点 \(j\),然后 \(dp_{i}=dp_{i}+(-1)^{i-j}dp_{j-1}\min\{r_j,……,r_i\}\),暴力做就可以做到 \(\Theta(n^2)\)

能不能再给力点啊?

做法一:

我们考虑随着 \(i\) 的增加,\(\min\{r_j,……,r_i\}\) 是怎么变化的,我们考虑一下维护一个单调栈,那么每次一定是 \(r_i\) 弹掉了若干比 \(r_i\) 大的数,也就是对 \(\min\{r_j,……,r_i\}\) 的影响是一个区间赋值!

那么我们可以开一棵线段树,维护 \((-1)^{i-j}dp_{j-1}\min\{r_j,……,r_i\}\) ,那么就是一个区间赋值,单点修改,区间求和,然后就做到了 \(\Theta(n\log n)\)

做法二:

更暴力的,直接记录 \(dp_{i,v}\) 表示当前到了第 \(i\) 个,当前区间的 \(\min =v\) ,转移时:

  • 如果不钦定那么 \(dp_{i,r_i}+=v\times dp_{i-1,v}\)
  • 如果钦定并且 \(r_i<v\),那么 \(dp_{i,r_i}+=(-1)dp_{i-1,v}\)
  • 如果钦定并且 \(r_i\geq v\),那么 \(dp_{i,v}=dp_{i-1,v}*(-1)\)

可以发现需要支持区间乘法,单点修改,区间求和,建一棵值域线段树即可。

如果要拓展到树上怎么做?把做法二的值域线段树改成线段树合并即可。

例五[ARC101E] Ribbons on Tree

我们转换一下容斥的对象,我们这次对树上的边容斥。

题目的限制是每条边至少被经过一次,那么我们就钦定一个边集,这里面的边都不被经过,此时有什么性质呢?

我们可以发现,每条不被经过的边把树划分成了若干个连通块,每个连通块是独立的!并且因为连通块内的边经不经过都无所谓,所以如果一个连通块大小为 \(S\),那么这个连通块的配对的方案数就是 \((S-1)(S-3)(S-5)……\),和树的形态是无关的。

那么我们考虑树形 DP,$dp_{x,i} $ 表示在 \(x\) 子树内,当前点所在连通块的大小为 \(i\) 的方案数的和,转移的时候,枚举 \(x\) 的儿子 \(y\) 以及 \(y\) 所在块的大小 \(j\),并考虑这条边被不被钦定:

  • 如果不钦定,那么让 \(x,y\) 所在连通块合并,大小相加。
  • 如果钦定,那么就用 \(y\) 的方案数乘上 \((j-1)(j-3)……\),对了还要乘上 \(-1\)

因为 \(i\leq siz_x\),所以复杂度就是树背包的复杂度 \(\Theta(n^2)\)

例六2487. 水仙花

计算有多少个长度为 \(n\),值域为 \([1,m]\) 的序列 \(a\),对于 \(i\in [1,n-1]\),下面两个条件至少满足一个:

  • \(a_i\leq a_{i+1}\)
  • \(a_i\bmod a_{i+1}>0\)

钦定若干 \(i\) 都不满足,也就是 \(a_{i}> a_{i+1},a_i\bmod a_{i+1}=0\),也就是 \(a_{i+1}\)\(a_i\) 的真因子。

和上面的类似,最终被钦定的构成若干段区间,那么因为真因子每次至少 /2,所以每段区间的长度不超过 \(\log_2n\)

预处理 \(f_{i,j}\) 表示长度为 \(i\),且第一个数是 \(j\) 的序列个数,转移枚举 \(j\) 的倍数,复杂度 \(\Theta(m\log ^2 m)\)

然后设 \(dp_{i}\) 表示考虑前 \(i\) 个的方案数,每次枚举一段区间转移即可,复杂度 \(\Theta(n\log m)\)

例七 [ZJOI2022] 树

非叶子是不好确定的,我们考虑把非叶子容斥成叶子。

对于每个点,有如下情况:

  • 第一棵树非叶子,第二棵树叶子:

    • 选择容斥,变成第一棵树叶子,第二棵树叶子。
    • 不选择容斥,变成第一棵树任意,第二棵树叶子。
  • 第一棵树叶子,第二棵树非叶子:

    • 选择容斥,变成第一棵树叶子,第二棵树叶子。
    • 不选择容斥,变成第一棵树叶子,第二棵树任意。

    \(dp_{i,j,k}\) 表示考虑前 \(i\) 个点,\([1,i]\) 在第一棵树上有 \(j\) 个叶子,\([i+1,n]\) 在第二棵树上有 \(k\) 个叶子,转移是:

    • \(dp_{i+1,j+1,k-1}+=(-1)dp_{i,j,k}(i-j)(n-i-1-k)\)
    • \(dp_{i+1,j,k-1}+=dp_{i,j,k}(i-j)(n-i-1-k)\)
    • \(dp_{i+1,j+1,k-1}+=(-1)dp_{i,j,k}(i-j)(n-i-1-k)\)
    • \(dp_{i+1,j+1,k}+=dp_{i,j,k}(i-j)(n-i-1-k)\)

    复杂度 \(\Theta(n^3)\)

例八 [NOI2020] 命运

对路径容斥,钦定若干路径上的边都是 \(0\),剩下的路径不限制。

考虑一个 \(dp\)\(dp_{i,j}\) 表示在 \(i\) 的子树内,当前还存在的路径中,上端点最浅的深度为 \(j\) 的方案数。

合并子树 \(dp_{y,k}\) 时,如果 \(k=dep_y\),这条边就 \(0/1\) 都可以选,否则就必选填 \(0\),同时令 \(j=\min (j,k)\)

加入路径时,如果不容斥就不更新,如果容斥就令 \(j=\min(j,k)\)

用线段树合并维护 dp 数组,需要打乘法标记,维护区间和。

复杂度 \(\Theta(n\log n)\)

1.2 二项式反演

所谓的二项式反演,其实是容斥的一种拓展情况,我们之前求的是所有元素都满足某个限制的个数,而二项式反演通常解决的是:恰好\(k\) 个元素满足某个限制的序列个数。

我们设这个问题的答案是 \(f_{k}\),仿照前面的思路,我们钦定 \(k\) 个元素满足限制,剩下任意,记为 \(g_{k}\)

那么 \(f,g\) 有什么关系呢,考虑对于 \(f_k,g_{j},k\geq j\),那么 \(f_{k}\)\(g_j\) 算了 \(\dbinom{k}{j}\) 次,也就是说:

\[g_{j}=\sum\limits_{k=j}^n\dbinom{k}{j}f_k \]

假如我们可以算 \(g\),那么怎么从 \(g\) 得到 \(f\) 呢,事实上:

\[f_{j}=\sum\limits_{k=j}^n(-1)^{k-j}\dbinom{k}{j}g_k \]

我们不妨展开右边式子:

\[\sum\limits_{k=j}^n(-1)^{k-j}\dbinom{k}{j}\sum\limits_{i=k}^n\dbinom{i}{k}f_i \]

\[=\sum\limits_{i=j}^nf_i\sum\limits_{k=j}^i(-1)^{k-j}\dbinom{i}{k}\dbinom{k}{j} \]

\[=\sum\limits_{i=j}^nf_i\sum\limits_{k=j}^i(-1)^{k-j}\dbinom{i}{j}\dbinom{i-j}{k-j} \]

\[=\sum\limits_{i=j}^n\dbinom{i}{j}f_i\sum\limits_{k=0}^{i-j}(-1)^{k}\dbinom{i-j}{k} \]

\[=\sum\limits_{i=j}^n\dbinom{i}{j}f_i[i-j=0] \]

\[=f_j \]

因此得证。

当然,因为恰好 \(k\) 个满足等于 恰好 \(n-k\) 个满足,所以通常情况是对 \(n-k\) 进行容斥的,和上面是一样的。

P10596 BZOJ2839 集合计数

\(f_k\) 表示钦定 \(k\) 个元素在他们的交集内,其他任意的方案数。

那么包含这 \(k\) 个集合的子集个数有 \(2^{n-k}\),选出至少一个的方案数是 \(2^{2^{n-k}}-1\),乘上选出 \(k\) 个元素的方案数 \(\dbinom{n}{k}\),然后二项式反演回原式即可。

已经没有什么好害怕的了

因为总共有 \(n\) 组,所以可以得出 “糖果比药片能量大” 的恰好有 \(\frac{n+k}{2}\) 组。

把糖果和药片都从小到大排序,设 \(f_{i,k}\) 表示考虑了前 \(i\) 小的糖果,其中钦定了 \(k\) 组的方案数,转移时,如果不钦定,我们可以最后乘上一个 \((n-k)!\) 即可;如果钦定,那么求出可以和第 \(i+1\) 个糖果在一组的药片数量 \(j\),其中已经有 \(k\) 个被用过了,所以方案数就是 \(j-k\)

最后二项式反演回原问题,复杂度 \(\Theta(n^2)\)

[NOI Online #2 提高组] 游戏

求出 \(g_k\) 表示恰好选出 \(k\) 对祖先-子孙点且颜色不同的方案数,最后乘上 \(m!\) 即可。

套路的,钦定若干对祖先-子孙点,设 \(f_{i,k}\) 表示 \(i\) 的子树内,钦定了 \(k\) 对节点的方案数。

合并子树就是背包,而对于节点 \(i\),不选择钦定的话最后乘上 \((m-k)!\) 即可,选择钦定的话,如果子树内有 \(s_i\) 个和 \(i\) 颜色不同的节点,那么可以和 \(i\) 匹配的就有 \(s_i-k\) 个,乘上即可。

最后二项式反演出 \(g\),复杂度 \(\Theta(n^2)\)

CF285E Positions in Permutations

还是求出钦定若干位置满足 \(|i-p_i|\) 的方案数,二项式反演回去。

\(f_{i,k}\) 表示前 \(i\) 个位置,钦定了 \(k\) 个的方案数,对于不被钦定的位置我们还是最后乘上 \((n-k)!\)

那么其实我们只关注 \(i,i+1\) 是否被选即可,复杂度 \(\Theta(n^2)\)

可以发现大部分二项式反演的题都是一个套路

1.3 另一些容斥问题

  • 有平面上的 \(k\) 个障碍,要求从 \((0,0)\) 开始,每次向上或者向右走到 \((n,m)\) 不能经过障碍点的方案数,\(0\leq k\leq 1000,n,m\leq 10^5\)

直接求很难求,我们钦定若干障碍点必须经过,其他的无所谓。

\(dp_{i}\) 表示钦定第 \(i\) 个障碍点必须经过时,从 \((0,0)\) 走到第 \(i\) 个障碍点的方案数。

转移时枚举上一个被钦定的障碍点 \(j\),那么方案数就是 \(dp_j\dbinom{x_i-x_j+y_i-y_j}{x_i-x_j}\)

复杂度 \(\Theta(n^2)\)

[THUPC2019] 过河卒二

首先,可以从上边和右边走出棋盘,等价于我们走到 \((n+1,m+1)\)

然后对于障碍点做上述的容斥 \(dp\),只不过不同的是这次可以斜着走。

假设我们要从 \((0,0)\) 走到 \((X,Y)\),枚举向右上走的次数 \(i\),那么方案数可以表示为:

\[\sum\limits_{i=0}^{\min(X,Y)}\dbinom{X+Y-i}{i}\dbinom{X+Y-2i}{X-i} \]

组合数用 lucas 算,复杂度 \(\Theta(mk^2)\)

[HAOI2017] 方案数

现在有三维了!有什么区别吗

容斥的部分和上面是一样的,我们的问题还是预处理从 \((0,0,0)\) 走到 \((X,Y,Z)\) 的方案数。

这个状态有点大啊,不过仔细分析一下会发现实际上只和 \(X,Y,Z\)\(1\) 的个数有关。

\(dp_{i,j,k}\) 表示走到 \(|X|=i,|Y|=j,|Z|=k\) 的方案数,转移的时候,枚举下一次操作,假设是操作 \(X\),那么转移应该是 \(dp_{i',j,k}=dp_{i',j,k}+dp_{i,j,k}\dbinom{i'}{i}\)
于是就做完了,复杂度 \(\Theta(o^2)\)

  • 求出 \(n\) 个点的无向连通图数量。

\(f_{i}\) 表示 \(i\) 个点的无向连通图数量,那么可以用 “总的图的数量” 减掉 “不连通的图的数量”。

前者就是 \(2^{n(n-1)/2}\),对于后者,我们枚举一号点所在连通块的大小 \(j(j<i)\),那么剩下的部分和这 \(j\) 个点不连通,转移为:

\[f_{i}=2^{n(n-1)/2}-\sum\limits_{j=1}^{i-1}\dbinom{i-1}{j-1}f_{j}2^{(i-j)(i-j-1)/2} \]

分别代表选出 \(j-1\) 个点组成连通块的方案数,连通块内部的方案数,以及外部的方案数。

复杂度 \(\Theta(n^2)\)

[清华集训2012] 串珠子

因为 \(n\) 很小,所以我们考虑状压。

\(g_S\) 表示集合 \(S\) 内部的点构成的图的总数,\(f_S\) 表示集合 \(S\) 内的点构成连通图的方案数,转移时还是枚举 \(1\) 所在连通块的点集。

\(f_S=g_S-\sum\limits_{T\subset S,1\in T}f_Tg_{S-T}\)

复杂度 \(\Theta(2^nn^2+3^n)\)

posted @ 2024-08-24 17:52  Larunatrecy  阅读(39)  评论(0编辑  收藏  举报