容斥原理

搬自我的洛谷专栏。

容斥原理:

好东西

一、理论:

为什么要用容斥原理:

  • 原来的条件不好做,但是反过来很好做(人们总是擅长破坏的)

怎么用容斥原理:

如果反过来正好是原条件的补集方案,那么直接用总方案减就OK了。

关键问题在于有多个条件的时候,将一个取反不是所有原条件的补集,因此需要凑配/递推容斥系数。

  • 若某种方案恰好满足 \(i\) 个条件包含,设这种方案的贡献系数为 \(f(i)\)

  • 若某种方案钦定满足 \(i\) 个条件 设这种方案的容斥系数为 \(g(i)\)

有:

\[f(n)= \sum\limits_{i=0}^{t}{n \choose i}g(i) \]

这样可以检验你配的容斥系数是不是正确的

比如说,非常典型的偶加奇减。

在这里,我们可以发现

\[f(i)= \begin{cases} 1,&i=0\\ 0,&i>0 \end{cases} \]

我们设置的容斥系数 \(g(i)=(-1)^i\)

检验:

\[f(n)= \sum\limits_{i=0}^{t}{n \choose i}g(i) \]

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

\[\begin{aligned} {f(n)} = & \sum\limits_{i=0}^{t}{n \choose i}g(i)&\\ = & \sum\limits_{i=0}^{t}{n \choose i}(-1)^i&\\ = & \sum\limits_{i=0}^{t}{n \choose i}(-1)^i\times1^{n-i}& = &(-1+1)^n& \end{aligned} \]

显然,只有\(f(0)=1\)

同样,还可以反过来递推容斥系数

根据式子:$
f(n)= \sum\limits_{i=0}^{n}{n \choose i}g(i)$

\[\begin{cases} g(0)=f(0)\\ g(i)=f(i)-\sum\limits_{j=0}^{i-1}{i \choose j}g(i) \end{cases} \]

哈哈哈,以后再也不用乱凑容斥系数啦。

有了容斥系数之后,我们就可以枚举容斥的基数,然后他的贡献即为:容斥系数 $\times $ 容斥价值

附:二项式定理:

\[(a+b)^n = \sum\limits_{i=0}^{n}{n\choose i} a^i \times b^{n-i} \]

二、例题

1.devu and flowers

暴力枚举所有条件集合,钦定这些选中条件取反,加上对答案的贡献:容斥系数 * 方案贡献即可。


2.P6076 [JSOI2015] 染色问题

考虑后三个条件,先看第一个:每一行至少一个

每一行至少一个这种玩意,相当于对每一行都有限制。

至少一个不好做,但是反过来,一个没有是好说的,直接把这行删了即可,其余任意。

我们直接将所有条件取反。

但是有问题,一个条件取反后的补集并不是所有条件取反的并集,因此需要配系数。

很显然这道题的容斥系数是简单的 \((-1)^i\)

继续考虑剩下的,发现都和第一个类似。

然儿,三个条件如何合并在一起呢。

实际上,就是三种容斥相乘,因为将每个单独的容斥列成函数合并后再展开,就是乘法分配律了。

直接有以下式子:

\[ans= \sum\limits_{c=0}^{cnt} \sum\limits_{i=0}^{n} \sum\limits_{j=0}^{m}{cnt \choose c}{n \choose i}{m \choose j}\times (-1)^{c+i+j} \times (cnt+1-c)^{(n-i)\times (m-j)} \]

注意在这里,我们将同一类容斥合并了,因为他们都有相同的容斥系数和容斥贡献,直接考虑他们的数量,因此出现了组合数。


3. 【COCI2009-2010#6】 XOR

这道题我们可以发现,贡献系数变了。

\[f(i)= \begin{cases} 1,&i \in odd\\ 0,&i \in even\\ \end{cases} \]

这咋办呢,可以先列出式子递推:

\[\begin{cases} f(n)= \sum\limits_{i=0}^{n}{n \choose i}g(i)\\ g(0)=f(0)\\ g(i)=f(i)-\sum\limits_{j=0}^{i-1}{i \choose j}g(i) \end{cases} \]

但是但是,这道题有坑,就是我们无法算出0个条件取反,就是0个三角形交的面积。

因此应该变为这样

\[\begin{cases} f(n)= \sum\limits_{i=1}^{n}{n \choose i}g(i)\\ g(1)=f(1)\\ g(i)=f(i)-\sum\limits_{j=1}^{i-1}{i \choose j}g(i) \end{cases} \]

然后就可以了,最终得出 \(g(i)=(-2)^{i-1}\)

证明:

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

得证。

注意此题实现的细节:

如果只存 \((x,y,r)\),会导致合并的时候出现顺序互相制约的问题:

更新r需要先更新x,y,而更新x,y又需要更新r

因此考虑直接存直线,这样就不必担心了。


4.[JSOI2011] 分特产

经典至少取反,然后容斥,不再赘述。

然后就是考虑,有 \(m\) 种小球,每种小球有 \(a_i\) 个,要分 \(n\) 个人,有多少种分发。

由于这个整体做很难,而且复杂度线性也不可能,因此考虑分步走。

我们可以发现如果分布就简单了,变为了非负整数不定方程解的个数,可以对应隔板法了。


二、“恰好与钦定”

一、理论部分:

问:为什么求恰好要用钦定。

因为有的时候,限制为恰好太困难了,因为你需要保证就这么多,不能多也不能少。

而钦定就相对简单了,你只需要满足钦定的,其余的就是随便填了。

这里说明一下钦定至少的区别。

看起来,这俩特别像,都是兜底是多少吗。

但是差别其实很大

(一) 统计中的差别

  • 钦定:先钦定再计算

  • 至少:直接统计。

举个例子,集合 \({1,2,3}\)

在钦定选择两个元素的 \(f(2)\)中,{1,2,3}这个集合会被统计

因为过程是这样的,钦定1,2要选,因此多一次;钦定1,3要选,{1,2,3}有被选了一次,钦定 {1,3}要选,因此{1,2,3}被选了三次。

但是在至少有两个元素的 \(s(2)\) 中,{1,2,3}只会被统计一次,因为它的元素个数至少有两个,会被算一次,如果只有1个,那就不会在这里被统计。

(二)贡献中的差别:

如果有至少 \(i\) 个的方案数 \(s(i)\),我们就可以直接差分出来恰好 \(i\) 个的:\(s(i+1)-s(i)\)

如果有钦定 \(i\) 个的方案树 \(f(i)\),那么我们可以通过二项式反演来求,或者递推。

问:怎么用钦定求恰好

我们设共有 \(n\) 个条件

恰好满足 \(i\) 个条件的方案有 \(g(i)\)

钦定满足 \(i\) 个条件的方案有 \(f(i)\)

\(f(i)\) 一般通过dp,组合计数等技巧算出,然后反演或递推出 \(g(i)\)

二项式反演:

形式1

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

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

没见过用的,但是很好背

形式2

\[f(n) = \sum\limits_{i=0}^{n}{n\choose i} {g(i)} \]

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

\(g(i)\) 表示恰好 \(i\) 个,\(f(i)\) 表示钦定只在 \(i\) 个里面选(最终选的是 \(i\) 的子集)

MX-NOI#4T1 Tree

题目大意:

每次选一个联通块保留,删掉剩余部分,要求删掉的部分非空。问恰好删 \(k\) 次删空的方案数。

每次非空是恰好,可以不限制每次非空,这样方便很多,最后反演就好了。

形式3

\[f(n)= \sum\limits_{i=n}^{N}{i \choose n} g(i) \]

\[g(n) = \sum\limits_{i=n}^{N}{i \choose n} (-1)^{i-n}f(i) \]

用的最多,\(g(i)\) 表示恰好 \(i\) 个,\(f(i)\) 表示钦定必须选 \(i\)个(最终选的是 \(i\) 的超集)

二、例题

1.P2167 [SDOI2009] Bill的挑战

这是一道二项式计数的入门题目。

当你看到恰好的时候,应该立马反映出要用到钦定做,然后反演求恰好。

好了,考虑钦定,这是在没什么好说的,直接状态压缩,暴力枚举每种状态即可,然后算出合法的字符串数量。

算出钦定 \(i\) 个的 \(f[i]\) 后根据二项式反演,直接求出 \(g[k]\)

为什么这是一道入门题目,是因为 \(f[i]\) 的得出过程过于简单,之后,难度将加在这里。


2.P4859 已经没有什么好害怕的了

首先,推出真正的 \(k\) 即 A 有多少个数是 \(> k\)的。

和差一定,直接相加 \(/2\) 即可,得到 \(k=(n+k)/2\)

然后题目转化为了,A和B每一位匹配,A恰好有 \(k\) 位比 \(B\) 大,有多少种方案。

套路的恰好转化为钦定,然后就要考虑 \(f[i]\) 的得出了。

因为没有顺序要求,因此这种比大小问题先排个序。

\(f[i][j]\) 表示匹配了前 \(i\) 个,有 \(j\) 个比B中的大。

  • 如果当前位没被钦定 : \(f[i][j]+=f[i-1][j]\)

  • 如果当前位被钦定:我们算出他最后一个能打过的数,之前的都可以选择,设位置为 \(r\),但由于之前已经选了 \(j\) 个,因此需要扣掉这些位置,\(f[i][j]+=f[i-1][j-1] \times (r-j+1)\)

但这就完了吗?绝对没有,钦定的含义是:钦定几个,其余任意。

最后要补上任意带来的贡献,也就是说,钦定了几个后,剩余的摆放位置都是任意的,因此要有 \(f[n][j] \times = (n-j)!\)


3.P6478 [NOI Online #2 提高组] 游戏

本题难点已经转移为了如何dp了。

首先我们可以抽象题意:恰好有 \(k\) 组分出胜负的方案数。

然后套路的恰好转为钦定,然后考虑求出 \(f[i]\)

\(f[u][j]\) 表示以 \(u\) 为根的子树中,钦定有\(j\)轮决出胜负的方案数。

首先先忽略根对答案的影响,考虑子树贡献。

容易发现可以子树合并,这里有一点就是开一个辅助数组可以很好的解决循环顺序的问题,根本不必担心。

具体的,先将合并后的答案存入 \(tmp[]\) 中,之后再放回来即可。

\[tmp[j+k]=f[u][j] \times f[son][k] \]

\[f[u][j]=tmp[j] \]

最后考虑根的贡献,如果不钦定根,那就是子树合并的结果,如果钦定根:

  • 如果他是白点,他可以和子树中的黑点匹配,但注意,这些点之前已经有被用过的了。

  • 如果他是黑点,同理。

有转移 \(f[u][j+1]+=f[u][j] \times sz[u][c[u]\oplus1]-j)\)

其中 \(sz[u][1/0]\) 表示 \(u\) 为根的字数内黑点或百点的个数。

注意,这样转移是 \(O(n^3)\) 的,需要卡一下钦定数量上界。

可以发现,即为 \(min(sz[u][0],sz[u][1])\),这样就可以保证复杂度 \(O(n^2)\)

posted @ 2025-04-08 21:15  Richard_whr  阅读(68)  评论(0)    收藏  举报