容斥原理
容斥原理
经典韦恩图
有 \(n\) 个集合 \(S_1,S_2,\dots,S_n\),设 \(U=\{S_1,S_2,\dots,S_n\}\),则
写成更简单的形式,就是容斥原理了。
也有一种常见写法,它跟上式本质上是一样的,只不过它先枚举了集合大小 \(i\),再枚举了具体集合 \(\{a_j\}\)。
不定方程非负整数解计数
给出不定方程 \(\sum\limits_{i=1}^nx_i=m\),以及 \(n\) 个限制条件 \(x_i\le b_i\),求方程的非负整数解个数。
这里会先介绍两种特殊情况:没有限制的情况,以及限制相同的情况,然后再引入更一般的做法。
没有限制
如果没有限制,相当于将 \(m\) 个球放入 \(n\) 个盒子中,允许为空,插板法得答案为 \(\binom{n+m-1}{n-1}\)。
限制相同
即限制条件为 \(x_i\le c\),其中 \(c\) 是常数。
此时考虑容斥,设 \(f(k)\) 表示钦定 \(k\) 个盒子超限的方案数。考虑如何计算 \(f(k)\),先选出 \(k\) 个盒子,在这些盒子中先放入 \(c+1\) 个球,这样相当于钦定它们超限。然后再将剩下的 \(m-k(c+1)\) 个球放入 \(n\) 个盒子中,这一部分用插板法计算即可。
设 \(g(k)\) 表示恰好 \(k\) 个盒子超限的方案数,答案即为 \(g(0)\),由二项式反演得
可以 \(O(n)\) 计算。
一般情况
标准的容斥原理
设 \(S_i\) 表示 \(x_i\) 满足限制的解的组数,即有多少组解 \(\{x_1,x_2\dots,x_n\}\) 满足 \(x_i\le b_i\)(指具体的一个 \(i\),而不是 \(i\in [1,n]\))
所求即为 \(\left|\bigcap\limits_{i=1}^nS_i\right|\),表示所有变量都满足条件的集合大小。
由于容斥原理计算的是 \(\left|\bigcup\limits_{i=1}^n S_i\right|\),所以我们考虑这样一个“交并容斥”的式子,其中 \(U=\{S_1,S_2,\dots,S_n\}\):
这里面 \(|U|\) 是很好算的,它表示没有限制的解的数量。而后面的式子是 \(\left|\bigcup S_i\right|\) 的形式,可以用容斥原理展开,则有
接下来就只需要算 \(\left|\bigcap\limits_{j=1}^m\complement_US_{a_j}\right|\) 了。考虑到 \(\complement_US_i\) 表示 \(x_i>b_i\) 的解的组数,所以\(\left|\bigcap\limits_{j=1}^m\complement_US_{a_j}\right|\) 就表示钦定 \(a\) 中的变量全部超限的解的组数。这个可以用组合数来算,看作球盒问题,对于钦定超限的 \(i\),先将 \(b_i+1\) 个球放入 \(x_i\)。然后将剩下的 \(m-\sum\limits_{j=1}^i(b_{a_j}+1)\) 个球放入所有 \(n\) 个盒子中,插板法即可。则
回代到最初求 \(\left|\bigcap\limits_{i=1}^nS_i\right|\) 的式子中,得
由于容斥的过程相当于枚举 \(U\) 的子集,因此直接计算的复杂度是 \(O(2^n)\)。
二项式反演
设 \(d(S)\) 表示钦定集合 \(S\) 中的变量超限时的解的数量,相当于 \(\left|\bigcap\limits_{j=1}^m\complement_US_{a_j}\right|\)。
设 \(f(k)\) 表示钦定 \(k\) 个变量超限时的解的数量,目标是“恰好 \(0\) 个变量超限”,则答案为 \(\sum\limits_{k=0}^n(-1)^k f(k)\)。这一步就是二项式反演。\(f(k)\) 也很好算:\(f(k)=\sum\limits_{\left|S\right|=k}d(S)\)。
例题
Problem 1:有一个随机生成器,每次会均匀随机地生成一个 \([0,m]\) 之间的整数。
用这个随机生成器生成了 \(2n\) 个整数,求前 \(n\) 个数的和比后 \(n\) 个数的和大的概率。
\(n,m\le 10^6\)
Source:FZOJ6525 Y
注意到前 \(n\) 个数的和与后 \(n\) 个数的和一共有三种关系:前<后,前>后,前=后。由于对称性,“前>后”与“前<后”的数量是相等的,所以我们只需要计算“前=后”的数量即可解出答案。
设前 \(n\) 个数的和为 \(x\),后 \(n\) 个为 \(y\)。我们将后 \(n\) 个数的值域变为 \([-m,0]\),问题就变为 \(x+y=0\) 的方案数。再将后 \(n\) 个数整体加 \(m\),则等价于求 \(x+y=nm\) 的方案数,即所有 \(2n\) 个数的和等于 \(nm\) 的方案数。
这就是上面介绍的“不定方程非负整数解问题”,并且是所有限制都相同的情况,容斥即可 \(O(n)\) 计算。
Problem 2:共有 \(4\) 种硬币。面值分别为 \(c_1,c_2,c_3,c_4\)。
某人去商店买东西,去了 \(n\) 次,对于每次购买,他带了 \(d_i\) 枚 \(i\) 种硬币,想购买 \(s\) 的价值的东西。请问每次有多少种付款方法。
\(n\le 1000\),\(1\le c_i,d_i,s\le 10^5\)
Source:[HAOI2008] 硬币购物
设第 \(i\) 种硬币用了 \(x_i\) 枚,所求即为下面这个方程的解的个数
沿用容斥的思路,设 \(f(S)\) 表示钦定集合 \(S\) 中的硬币超限时解的个数,则答案为 \(\sum\limits_{S\subseteq U}(-1)^{\left|S\right|}f(S)\),其中 \(U=\{1,2,3,4\}\)。
考虑如何计算 \(f(S)\),首先对于钦定超限的 \(x_i\),我们拿出总数 \(s\) 中的 \(d_i+1\) 分配给 \(x_i\),这样它一定超限。然后就只需要计算所有 \(x_i\) 在无限制的情况下使总价值为 \(s-\sum\limits_{i\in S}c_i(d_i+1)\) 的方案数,由于没有限制,可以直接用一个DP预处理。复杂度 \(O(4s+4\cdot 2^4\ n)\),提交记录。