容斥原理学习笔记

前言

可能需要一点二项式定理和二项式反演的相关知识。

有许多不足还请指出。

公式

经典容斥

A1,A2,,An 均为有限集,AiS,则

|i=1nAi|=k=1n(1)k11i1<i2<<ikn|Ai1Ai2Aik|

可以用数学归纳法严格证明,我有个简单点的。

考虑 S 中任一元素 x,若共有 m 个集合包含 x,其对答案的贡献为

k=1m(mk)(1)k1=k=1m(mk)(1)k=k=0m(mk)(1)k+1=(11)m+1=1

即每个元素都仅对答案产生 1 的贡献。

组合容斥

组合容斥中,容斥系数变为了组合数。

有个简单的引例,若 g(S)=STf(T),则有

f(S)=ST(1)|T||S|g(T)

证明如下:

LHS=ST(1)|T||S|g(T)=ST(1)|T||S|TQf(Q)=SQf(Q)STQ(1)|T||S|=SQf(Q)TQS(1)|T|

考察式子右半边,令 F(S)=TS(1)|T|,则

F(S)=i=0|S|(1)i(|S|i)=(11)|S|=[|S|=0]

LHS=SQf(Q)[QS=0]=f(S)

现在改变 f,g 的含义,f(i),g(i) 表示所有 |S|=if(S),g(S) 之和,发现每个大小为 i 的集合任选 k 个都会对 g(k) 产生 f(i) 的贡献,即 g(k)=i=kn(ik)f(i),由二项式反演得

f(k)=i=kn(1)ik(ik)g(i)

有的题容斥系数可能更为复杂,对于如何求容斥系数,可以对每种情况考虑其应被计算次数,并列出方程来求解。

minmax 容斥

给定集合 Smax(S) 表示 S 中最大值,min(S) 表示 S 中最小值,则有

max(S)=TS(1)|T|1min(T)

min(S)=TS(1)|T|1max(T)

对第一个式子证明。将 S 中的元素从大到小排序,考虑第 k+1 大的应元素被计算几次。

对于第 k+1 大的元素,当它以 min(T) 呈现时,说明 T 中的元素均是第 1 至第 k+1 大的,且必须包含第 k+1 大的元素。

故第 k+1 个数会被计算 i=0k(ki)(1)i=(11)k=0 次。

特别地,当 k=0 时,会被计算一次,即只有 max(S) 被计算了一次。

min(S) 的证明同理。

minmax 容斥还可以推广到第 k 大,maxk(S) 表示集合 S 中第 k 大的元素,设 f(i) 为容斥系数,则 maxk(S)=TSf(|T|)min(T)

对于第 x+1 大的元素,我们希望它被计算 [x+1=k] 次,可列出方程

[x+1=k]=i=0x(xi)f(i+1)

由二项式反演得

f(x+1)=i=0x(1)xi(xi)[i+1=k]=(1)x(k1)(xk1)

f(x)=(1)xk(x1k1)

maxk(S)=TS(1)|T|k(|T|1k1)min(T)

主要用来解决集合概率问题。

例题

BZOJ3589 动态树

给你一棵 n 个点的树,q 次操作,支持

  1. u 子树内每个点权加 k
  2. 查询 k 条链的并集点权和

保证给出的链深度递增。

1n,q2×105,1k5


直接求并不好求,可以用容斥把问题转化为枚举 2k 种情况求交,这题的链深度递增,求交是相当简单的。

直接树剖维护是 O(2knlog2n) 的,去到了 109

因为这题的链深度递增,所以链求和可以直接维护到根的路径上点权和,作差就可以了,这样一次修改是 O(logn),一次查询是 O(2klogn),总复杂度是 O(2knlogn),去掉了一个 log

然后对于 u 子树内的一点 v,一次加 k 会使 v 处增加 (depvdepu+1)×k=depv×k(depu1)×k,前后两部分分开维护即可。


CQOI2012 局部极小值

对于一个 n×m 的矩阵,ai,j 被认为是好的当且仅当 ai,j 比其周围 8 个数均更小。给出矩阵中好的元素位置,求可能的矩阵方案数。

所有的 ai,j 构成一个 [1,nm] 的排列。

1n4,1m7


为保证构造矩阵合法,可以从小到大填数,目标位置周围显然不能填。

发现最多可存在的好的元素数量很少,可以把这些位置压缩成一个状态进行 dp,关键点位置的转移直接从前驱转移即可,未填数的关键点周围不可转移,其他位置随便放即可,转移方程很好写。

注意到这样 dp 出来的方案数可能会包含更多的关键点,所以要容斥一下,具体而言,若题目给出 i 个关键点,最多存在 p 个关键点,则答案为 k=0pi(1)kfi+k

因为 p 很小,所以直接搜索,在原有集合上扩展,每次把多一个的答案减掉即可。

复杂度不太会算,跑得挺快。


P4859 已经没什么好害怕的了

给出序列 a,b,一个排列 p 的权值为 i=1n[ai>bpi],求权值为 k 的排列个数。

1n2×103


简化题意的 k 是原题的 n+k2

考虑 dp,先将 a,b 排序,发现当 ai 选择一个比它小的 bpi 时,对后面的选择不会有本质影响,而选择比它大的 bpi 会很复杂。

这启发我们在 dp 中设计匹配个数的状态,最后统一分配剩下的 bifi,j 表示考虑到第 i 项,有 jk 满足 ak>bpk 的情况数,记 qi 表示 b 序列中比 ai 小的元素个数个数,有转移方程 fi,j=fi1,j+(qij+1)fi1,j1

之后考虑剩下 bi 对答案的影响,令 gi=(ni)!fn,i,表示剩下的数任意放的情况数,发现可能会产生更多的匹配,且同一种排列可能会被计算多次,考虑组合容斥。

hi 表示权值恰好等于 i 的排列数,有

gk=i=kn(ik)hi

可以理解为 hi 中的每种排列从 i 个匹配中任取 k 个出来都会对 gk1 的贡献。

由二项式反演得

hk=i=kn(1)ik(ik)gi


SCOI2010 幸运数字

一个数字是幸运数字当且仅当它每一位均由 68 组成。

一个数字是类幸运数字当且仅当它是幸运数字的倍数。

求区间 [l,r] 内类幸运数字的个数。

1lr1010


发现最多只有 2046 个幸运数字,记为序列 a,可以预处理出来,令 n 表示幸运数字个数。

问题转化为 [l,r] 中有多少个数是 a 中任意一个数的倍数。

这就是个经典的容斥问题了,其实就是若干个集合求并。

f(i) 表示 [l,r]i 的倍数个数,则

ans=k=1n(1)k11i1<i2<<iknf(lcm(ai1,ai2,aik))

直接做是 O(2n) 的,考虑一些剪枝。

首先可以把这里面有倍数关系的都去掉,这样只剩 943 个数了。

因为 lcm 大于 r 时肯定不会有贡献了,可以直接返回,这让复杂度大大降低。

然后可以将 a 从大到小排序,让 lcm 更快超过 r

这三个剪枝加完就能通过本题了。


BZOJ2839 集合计数

一个 n 个元素的集合,从它的子集(包括空集)中取出若干个集合,使它们的交集大小为 k,求可能的取法总数。

1n106,0kn


fi 表示交集大小至少为 i 的答案,首先钦定 i 个交集的元素,共有 (ni) 种情况,剩下的 ni 个数组成的集合,共有 2ni 个子集,每个子集可以选或不选,但不能都不选,要去掉空集,所以共有 22ni1 种取法,即 fi=(ni)(22ni1)

这样也会有一个集合内相同元素算了多次的问题,考虑组合容斥,令 gi 表示交集大小恰为 i 的答案,有

fk=i=kn(ik)gi

可理解为在交集 i 个元素中钦定 k 个作为 fk 中的交集,每次有 gi 贡献。

由二项式反演得

gk=i=kn(1)ik(ik)fi


HDU4336 Card Collector

n 种卡牌,每一时刻有 pi 的概率得到其中一种,保证 i=1npi=1,求每种卡牌得到至少 1 张的期望时间。

1n20


minmax 容斥基础运用,令 max(S) 表示集合 S 中拿到最后一张牌所需时间,min(S) 表示集合 S 中拿到第一张牌所需时间,有

E(max(S))=TS(1)|T|1E(min(T))

E(min(S))=1iSpi

O(2n) 求解。


HAOI2015 按位或

有一个数,初始为 0,每一时刻会选择一个 [0,2n) 内的数,与该数进行或操作。选择 i 的概率是 pi,保证 i=02n1pi=1。问该数变为 2n1 的期望时间。

1n20


把数抽象成集合,容易看出是刚才那题的加强版。

max(S) 表示集合 S 中拿到最后一个数被或上所需时间,min(S) 表示集合 S 中或上第一个数所需时间,有

E(max(S))=TS(1)|T|1E(min(T))

E(min(S))=1STpT

求交集不为空不好弄,可以反着求交集为空的和,STTS 补集的子集,即做一个子集求和,FWT 即可。

时间复杂度 O(2nn)


P4707 重返现世

n 种元素,每一时刻有 pim 的概率得到其中一种,保证 i=1npi=m
求得到 k 种元素的期望时间。

1n103,1m104,k[n10,n]


一道扩展 minmax 容斥神仙题。

min(S) 表示集合 S 中得到第一个元素所需时间,maxk(S) 表示集合 S 中所需时间第 k 大的元素,得到它的时间。因为题目给的是第 k 小,而这里的是第 k 大,为方便处理,令 k=nk+1,这样 k 变得很小。

可以写出扩展 minmax 容斥的期望形式。

E(maxk(S))=TS(1)|T|k(|T|1k1)E(min(T))

E(min(S))=miSpi

直接做复杂度爆炸,考虑对 E(min(T)) 相同的一块处理容斥系数。

Si 表示由 [1,i] 内的若干个数组成的集合。

做一个 dp,fi,j,k 表示所有 TSixTpx=j,参数为 k 时所有 (1)|T|k(|T|1k1) 之和,答案即为 i=1mfn,i,kmi

考虑转移,当 i 不纳入 Si 中时,fi,j,k=fi1,j,k

i 纳入 Si,则会贡献

TSi(1)|T|k(|T|1k1)=TSi(1)|T|k(((|T|1)1(k1)1)+((|T|1)1k1))=TSi(1)(|T|1)(k1)(((|T|1)1(k1)1)+((|T|1)1k1))=TSi(1)(|T|1)(k1)((|T|1)1(k1)1)+TSi(1)(|T|1)(k1)((|T|1)1k1)=TSi(1)(|T|1)(k1)((|T|1)1(k1)1)TSi(1)(|T|1)k((|T|1)1k1)=TSi1(1)|T|(k1)(|T|1(k1)1)TSi1(1)|T|k(|T|1k1)=fi1,jpi,k1fi1,jpi,k

时间复杂度 O(nmk),这里的 k 是新定义的。

后记

这是我第一次写这么长的博客,感觉比较典型的题里面都有了。

参考了学长的容斥原理 pdf,5 年前的 pdf 讲的很细致,感谢 dtz 学长。

只讲了一些最基础的内容,不知道能不能算是容斥原理入门。

posted @   Terac  阅读(137)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示