
排列组合#
四个计数原理#
-
加法原理:并列的方案数加和。
-
乘法原理:叠加的方案数相乘。
-
减法原理:正难则反,补集转换。
-
除法原理:目测用处不大。
排列组合定义式#
Amn=n!(n−m)!,Cmn=(nm)=n!m!(n−m)!
组合数的一些变换 1#
最基本的对称性:
(nm)=(nn−m)
根据定义得到:
(nk)=nk(n−1k−1)
可以考虑组合意义的一个变换:
(nm)(mk)=(nk)(n−km−k)
根据杨辉三角得到:
(nm)=(n−1m−1)+(n−1m)
进而推出(考虑杨辉三角上一纵列):
n∑i=0(ik)=1+n∑i=k+1(ik)=(k+1k+1)+n∑i=k+1(ik)=(n+1k+1)
Lucas 定理#
(nm)≡(nmodpmmodp)(⌊n/p⌋⌊m/p⌋)(modp)
证明:
(k+1)p≡kp+1(modp)
求组合数实际上就是求一个二项式的某一项,将 n,m 分解,n=ap+b,m=cp+d
(k+1)n≡(k+1)ap(k+1)b≡(kp+1)a(k+1)b(modp)
而 m 项就是:
(nm)km=(ac)kcp(bd)kd
所以上式成立。
于是在模 p 定义下,组合数可以拆分成 p 进制类的数。
组合数的一些求法#
-
规模小数量多:杨辉三角预处理。
-
规模数量适中:预处理阶乘以及逆元。
-
规模大:Lucas 定理
特殊组合数 1#
- 多重集排列数(xi 个 ai 组成的本质不同序列个数):
(nx1,x2,⋯,xk)=n!∏ki=1xi!
- 无限多重集组合数:等价于求 ∑ki=1xi=n 非负整数解的个数。令 yi=xi+1,就是在求 ∑ki=1yi=n+k 的正整数解个数,后者可以插板法:
(n+k−1k−1)
Qmn=Amnm
二项式系数#
二项式定理#
(x+y)n=n∑i=0(ni)xiyn−i
证明考虑组合意义,从 n 个 x 中选取 i 个,其余为 y 的方案数即为某一项的系数。
组合数的一些变换 2#
二项式定理的两个特殊情况:
n∑i=0(ni)=2n
n∑i=0(−1)i(ni)=[n=0]
对上一个式子中 n≥1 前提下的进一步解释:按考虑 i 的奇偶两边展开,也就是 n 个数选取奇数个和偶数个的方案数,显然前 n−1 个任意选,最后一个按照要求补全即可,于是两边都是 2n−1。
一个加权的式子:
n∑i=1i(ni)=n2n−1
第一种证明是基于上面提出一个分式的转换:
n∑i=1i(ni)=n∑i=1i×ni(n−1i−1)=n−1∑i=0n(n−1i)=n2n−1
也可以写成二项式再求导:
n∑i=0(ni)xi=(1+x)nn∑i=1i(ni)xi−1=n(1+x)n−1
代入 x=1,即证。
接下来考虑扩展到 i2,在代入前式子的基础上处理:
n∑i=1i(ni)xi=n(1+x)n−1xn∑i=1i2(ni)xi−1=n[(n−1)(1+x)n−2x+(1+x)n−1]
同样代入 x=1,得到:
n∑i=1i2(ni)=n(n+1)2n−2
容斥原理#
经典容斥模型#
集合 U 中每个元素都满足一些属性 P,其中满足属性 Pi 的元素构成了集合 Ai,现在给定集合 S,欲求出至少满足 S 中一种属性的元素个数(并集),以及同时满足 S 中所有属性的元素个数(交集)。
∣∣
∣∣⋃i∈SAi∣∣
∣∣=∑T⊆S,T≠∅(−1)|T|−1∣∣
∣∣⋂j∈TAj∣∣
∣∣
若求交集只需做一个补集转换:
∣∣
∣∣⋂i∈SAi∣∣
∣∣=|U|−∣∣
∣∣⋃i∈S¯¯¯¯¯¯Ai∣∣
∣∣
我们现在对这个模型给出证明,目的是证明每个符合条件的元素都不重不漏的只计算了一次。
考虑前面二项式中选择个数为偶数奇数方案数的例子,和这里是有相同之处的,对于一个元素 i,其满足的属性集合为 Bi,那么当且仅当 T⊆Bi 是才会对 i 的数量产生影响,也就是枚举 Bi 的非空子集。
而这里恰好就是选取奇数做正贡献,选取偶数做负贡献,而空集情况已经排除,那么奇数贡献正好比偶数多 1,即证不重不漏。
所以容斥最好的地方在于,正常求解对属性卡的非常严,而转化成交集后,只需考虑给出的部分满足,不需要考虑不给出的部分不满足。
特殊组合数 2#
- 有限多重集组合数(每个元素有一个 ni 的数量限制):考虑容斥,要求每个限制都满足,可容斥求至少一个限制不满足的方案,即枚举每一个超出限制的集合,其方案数是总数削去所有超过限制元素的 ni+1 后的普通答案。
(n+k−1k−1)−∑T⊆U,T≠∅(−1)|T|−1(n+k−∑i∈T(ni+1)−1k−1)
使用容斥原理的通项式:
Dn=n!−n∑k=1(−1)k−1(nk)(n−k)!=n!−n!n∑k=1(−1)k−1k!=n!n∑k=0(−1)kk!
于是简单推导可以得出第一个递推式:
Dn=nDn−1+(−1)n
如果考虑组合意义可以得出第二个递推式:
⎧⎨⎩D1=0D2=1Dn=(n−1)(Dn−1+Dn−2)n≥3
考虑满足条件的排列第一个数字取值为 [2,n],因此实际是钦定 2 为首个数字后的方案数的 n−1 倍。
当第二位上是 1 时,后面 n−2 个位置就是标准的错排,也就是 Dn−2,当第二位上不是 1 是,后面 n−1 个位置各自有自己的限制(1 不能出现在第二位,其余不能出现在对应位置),也就是 Dn−1,即证上式。
子集反演#
f(S)=∑T⊆Sg(T)⇔g(S)=∑T⊆S(−1)|S|−|T|f(T)
f(S)=∑S⊆Tg(T)⇔g(S)=∑S⊆T(−1)|T|−|S|f(T)
正确性直接代入即可。
二项式反演#
考虑容斥模型中大小相同的集合对应函数值相等的特殊情况,令 f(n) 表示同时满足 n 个条件对应原集的方案数,g(n) 表示 n 个满足 n 个条件对应补集的方案数,其中 f(0)=g(0)=|U|。
由容斥模型:
∣∣
∣∣⋂i∈SAi∣∣
∣∣=|U|−∣∣
∣∣⋃i∈S¯¯¯¯¯¯Ai∣∣
∣∣=|U|+∑T⊆S,T≠∅(−1)|T|∣∣
∣∣⋂j∈T¯¯¯¯¯¯Aj∣∣
∣∣
f(n)=g(0)+n∑i=1(−1)i(ni)g(i)=n∑i=0(−1)i(ni)g(i)
而原集与补集是相对概念,f 与 g 彼此的表达形式应当相同。
f(n)=n∑i=0(−1)i(ni)g(i)⇔g(n)=n∑i=0(−1)i(ni)f(i)
把左式的 (−1)i 并入 g(i) 中,得到:
f(n)=n∑i=0(ni)g(i)⇔g(n)=n∑i=0(−1)n−i(ni)f(i)
证明可以直接代入,运用组合数的恒等式。
继续扩展得到:
f(n)=n∑i=m(ni)g(i)⇔g(n)=n∑i=m(−1)n−i(ni)f(i)
f(n)=m∑i=n(in)g(i)⇔g(n)=m∑i=n(−1)i−n(in)f(i)
这里 f 与 g 的定义与容斥中的类似,分别表示钦定和恰好,恰好不用解释,而钦定不是至少,是 存在重复方案的,即枚举每个大小相等的子集,在保证满足这个子集的前提下其余任意,这样的方案数之和。
二项式反演可以同样可以由子集反演得到(是特殊情况)。
min-max 容斥#
先放出式子:
maxi∈Sxi=∑T⊆S,T≠∅(−1)|T|−1minj∈Txj
mini∈Sxi=∑T⊆S,T≠∅(−1)|T|−1maxj∈Txj
用语言描述就是:一个集合的最值等于其所有非空子集的另一最值做出的容斥。
证明考虑对于从小到大第 k 的值,映射到一个 [1,k] 的整数集合,取 min 等价于集合取交集,而 max 等价于取并集,这样相当于是就全集映射到的集合之并,自然等价于各个子集映射到的集合之交。
思考 min 与 max 同时总能想到 gcd 与 lcm,于是有:
lcmi∈Sxi=∏T⊆S,T≠∅(gcdj∈Txj)(−1)|T|−1
另外期望具有线性性,于是,就可以有:
E(maxi∈Sxi)=∑T⊆S,T≠∅(−1)|T|−1E(minj∈Txj)
这个用处很大,对于期望的问题,有时要求满足多个条件的期望,即求最大值的期望,而这往往不好求,相对简单的是去求一个集合的最小值期望,这是我们只需要关心什么时候首次满足条件即可。
特殊计数序列#
Catalan 数#
考虑一个由 n 个 +1 和 n 个 −1 构成的序列,要求这个序列任意一个前缀和都是非负数,求序列个数。
容易得到总的序列个数应当为 Cn2n,现在想要求出不合法的方案数。
对于一个不合法序列,找到第一个不满足的位置,截至这个位置的前缀是 k 个 +1 与 k+1 个 −1 组成的,把这个前缀每个位置取相反数,从而得到一个 n+1 个 +1 和 n−1 个 −1 构成的序列,这样的序列有:Cn+12n 个。
得到 Catalan 数的第一个表达式:
Cn=(2nn)−(2nn+1)=(2nn)n+1
进一步可以得到递推式:
Cn=4n−2n+1Cn−1
考虑 Catalan 数的组合意义就是上面提到的 +1 与 −1 序列,概括的说是在任意时刻,一种元素的个数总是不少于另一种,于是得到两个比较经典的模型:
-
从 (0,0) 走到 (n,n),每次可以纵向或横向增加一个单位,要求任意时刻所在位置 (x,y) 保证 x≥y,求方案数。(横向移动次数不少于纵向移动次数)
-
n 对括号构成的合法括号序列方案数。(左括号个数不少于右括号个数)
-
n 个元素入栈出栈顺序。(入栈次数不少于出栈次数)
对于上面的第二个例子,我们单独拿出最左侧的左括号以及其对应的右括号,这样会将整个括号序列划分成两个互不影响的合法子序列,枚举两个子序列大小得到:
Cn=n−1∑i=0Ci×Cn−1−i
观察这种划分成两个部分的组合意义,这等价于 n 个节点构成二叉树的方案数。
第一类 Stirling 数#
定义 [nm] 为第一类 Stirling 数,将 n 个元素形成 m 个圆排列(两个圆之间无顺序差别)的方案数,
递推式:
[nm]=[n−1m−1]+(n−1)[n−1m]
每个圆排列集合都唯一对应一个置换(每个圆是一个循环置换),而置换有 n! 个,于是:
n∑i=0[ni]=n!
上升幂转普通幂:
x¯¯¯n=n∑i=0[ni]xi
归纳法证明:
x¯¯¯¯¯¯¯¯¯¯n+1=x¯¯¯n×(x+n)=n∑i=0[ni]xi×(x+n)=n+1∑i=0[ni−1]xi+n∑i=0n[ni]xi=n+1∑i=0[n+1i]xi
由于上升幂与下降幂的关系:
x¯¯¯n=(−1)n×(−x)n––
xn––=(−1)n×(−x)¯¯¯n
代入到上面即可得到下降幂转普通幂:
xn––=n∑i=0(−1)n−i[ni]xi
第二类 Stirling 数#
定义 {nm} 为第一类 Stirling 数,将 n 个元素划分到 m 个非空集合(两个集合之间无顺序差别)的方案数。
递推式:
{nm}={n−1m−1}+m{n−1m}
使用二项式反演可得另一通项公式:
设 gn(m) 为 n 个元素放入 m 个集合(可以为空,两个集合之间有顺序差别)的方案数,显然 gn(m)=mn。
而 fn(m) 为 n 个元素放入 m 个集合(不能为空,两个集合之间有顺序差别)的方案数,有:
gn(m)=m∑i=0(mi)fn(i)
二项式反演得到:
fn(m)=m∑i=0(−1)m−i(mi)gn(i)
f 与第二类 Stirling 数的唯一区别是集合是否有顺序差别,也就是:
{nm}=f(m)m!=m∑i=0(−1)m−iini!(m−i)!
普通幂转下降幂(或者是组合数):
xn=n∑i=0{ni}xi–=n∑i=0{ni}i!(xi)=n∑i=0(xi)i∑j=0(ij)(−1)i−jjn
这里证明可以用组合意义,xn 即为 n 个元素放入 x 个有顺序差别集合中的方案数,枚举有 i 个集合非空,其选取方案、放置方案以及顺序差别三者的积即为上式。
实际应用中,通常转为组合数后进行组合数的变换。
同样的方式得到普通幂转上升幂:
xn=n∑i=0(−1)n−i{ni}x¯i
参考资料#
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效