Inclusion exclusion principle old
部分内容摘录自 OI-Wiki
我这里 Mathjax 不会显示 \overline
,所以用了 \overrightarrow
代替。
容斥原理ψ(`∇´)ψ
设 U 中元素有 n 种不同的属性,而第 i 种属性称为 \(P_i\),拥有属性 \(P_i\) 的元素构成集合 \(S_i\),那么
即
\(a_i\) 是用来枚举集合的。
证明ψ(`∇´)ψ
对于每个元素使用二项式定理计算其出现的次数。对于元素 x,假设它出现在 \(T_1,T_2,\cdots,T_m\) 的集合中,那么它的出现次数为
于是每个元素出现的次数为 1,那么合并起来就是并集。证毕。
补集ψ(`∇´)ψ
对于全集 U 下的 集合的并 可以使用容斥原理计算,而集合的交则用全集减去 补集的并集 求得:
右边使用容斥即可。
应用ψ(`∇´)ψ
不定方程非负整数解计数ψ(`∇´)ψ
给出不定方程 \(\sum_{i=1}^nx_i=m\) 和 \(n\) 个限制条件 \(x_i\leq b_i\),其中 \(m,b_i \in \mathbb{N}\). 求方程的非负整数解的个数。
没有限制时ψ(`∇´)ψ
如果没有 \(x_i<b_i\) 的限制,那么不定方程 \(\sum_{i=1}^nx_i=m\) 的非负整数解的数目为 \(C_{m+n-1}^{n-1}\).
略证:插板法。
相当于你有 \(m\) 个球要分给 \(n\) 个盒子,允许某个盒子是空的。这个问题不能直接用组合数解决。
于是我们再加入 \(n-1\) 个球,于是问题就变成了在一个长度为 \(m+n-1\) 的球序列中选择 \(n-1\) 个球,然后这个 \(n-1\) 个球把这个序列隔成了 \(n\) 份,恰好可以一一对应放到 \(n\) 个盒子中。那么在 \(m+n-1\) 个球中选择 \(n-1\) 个球的方案数就是 \(C_{m+n-1}^{n-1}\)。
容斥模型ψ(`∇´)ψ
接着我们尝试抽象出容斥原理的模型:
- 全集 U:不定方程 \(\sum_{i=1}^nx_i=m\) 的非负整数解
- 元素:变量 \(x_i\).
- 属性:\(x_i\) 的属性即 \(x_i\) 满足的条件,即 \(x_i\leq b_i\) 的条件
目标:所有变量满足对应属性时集合的大小,即 \(|\bigcap_{i=1}^nS_i|\).
这个东西可以用 \(\left|\bigcap_{i=1}^{n}S_i\right|=|U|-\left|\bigcup_{i=1}^n\overrightarrow{S_i}\right|\) 求解。\(|U|\) 可以用组合数计算,后半部分自然使用容斥原理展开。
那么问题变成,对于一些 \(\overrightarrow{S_{a_i}}\) 的交集求大小。考虑 \(\overrightarrow{S_{a_i} }\) 的含义,表示 \(x_{a_i}\geq b_{a_i}+1\) 的解的数目。而交集表示同时满足这些条件。因此这个交集对应的不定方程中,有些变量有 下界限制,而有些则没有限制。
能否消除这些下界限制呢?既然要求的是非负整数解,而有些变量的下界又大于 \(0\),那么我们直接 把这个下界减掉,就可以使得这些变量的下界变成 \(0\),即没有下界啦。因此对于
的不定方程形式为
于是这个也可以组合数计算啦。这个长度为 \(k\) 的 \(a\) 数组相当于在枚举子集。
CF997C Sky Full of Starsψ(`∇´)ψ
有一个 \(n\times n\) 的正方形网格,每个网格用 RGB 三种颜色染色
求有多少种方案使得至少有一行或者一列的颜色完全一致,模 \(998244353\)。
\(n \le 1e6\)。
我们考虑抽象出容斥的模型:
- 全集 U :所有可能的染色方式,方案数是 \(3^{n\times n}\)。
- 元素 :染色方式。
- 属性:(更好的理解是“一种限制/条件”)一行或者一列涂的颜色完全相同。
发现属性本质上就是 \(2n\) 个限制,也就是第 \(i\) 行全相同,第 \(i\) 列全相同这样的 \(2n\) 个条件。
要求的东西是至少有一行或者一列的限制/条件被满足的方案数。
也就是说我们如果设 \(S_i\) 表示所有满足第 \(i\) 个属性/限制的染色方案构成的集合,
显然不能直接把所有 \(|S_i|\) 相加,肯定会算重,那么考虑容斥,要求的答案就是 \(|\bigcup S_i|\)。
这个东西可以类比最简单的容斥,类似求 \(100\) 以内有多少数至少含有 \(2,3,5\) 其中一个因数。
写出来就是:
其中 \(S\) 表示若干个 \(S_i\) 的交,\(f(S)\) 表示这种情况的贡献。
考虑 \(S\) 表示有某 \(i\) 行,某 \(j\) 列是相同的情况,那么可以发现,选出来的这 \(i\) 行 \(j\) 列的颜色都是一样的。
我们现在就相当于 强制 这 \(i\) 行 \(j\) 列是同一种颜色,剩下的 \((n - i)(n - j)\) 个格子就随便选(就算又有新的相等的也不管,因为这里是强制,也就是只考虑被限制的部分,其他的部分都直接容斥掉了)。
因为 \(i\) 行 \(j\) 列是可以任意选的(这里只是考虑某个固定状态),那么 \(f(S)\) 就是 \(\dbinom{n}{i}\dbinom{n}{j}3^{1 + (n - i)(i - j)}\)
可以得知:
考虑枚举 \(i\),把式子拆开:
后面那坨看起来像二项式定理,把 \(j=0\) 补上之后减去再用二项式定理:
然后就可以 \(O(n \log n)\) 做了。
代码实现有几个细节,注意减法之后要加mod,然后尽量用 i64 做运算避免忘记乘 1ll。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
|