组合数学习笔记
定义:
排列:从 n 个元素中选取 r 个元素,当考虑顺序时,所有可能的方案一共有:
Anr=(n−m)!n!
组合:从 n 个元素中选取 r 个元素,当不计顺序时,所有可能的方案一共有:
Cnr=(nr)=m!(n−m)!n!=AmmAnm
组合数递推公式
如果将杨辉三角形写出来的话:
11111⋯1234⋯136⋯14⋯1⋯⋯
会发现这个三角形中的第 (i,j) 项恰好对应了组合数 Cij ,所以我们可以直观的得到这样一个式子:
Cnm=Cn−1m−1+Cn−1m
一种证明方法是将组合数的式子带进去算,但这样证明太复杂了。
另一种证明方法:在 n 个元素中选取 m 个元素中,考虑元素 m 有选与不选两种情况;当选 m 时,则需要在剩下 n−1 个元素中选取 m−1 个元素,当不选 m 时,则需要在剩下 n−1 个元素中选取 m 个元素。根据加法原理, Cnm=Cn−1m−1+Cn−1m 。
- 在后续证明中,将组合数的计算公式带入显然是一个万能的方法,但如果我们考虑好 Cnm 的意义,证明就会更容易些。
组合数及其相关性质
- Cn+mn=Cn+mm
显然 n+m个物品中 选 n 个元素的方案数等于挑出 m 个元素不选的方案数。
-
Cnm=Cn−1m−1+Cn−1m
-
Cn+r+1r=Cn+rr+Cn+r−1r−1+⋯+Cn0
反复套用上一个性质就可以证明。
- CnlClr=CnrCn−rl−r
对于 n 个元素,先无序取出其中 l 个元素,再无序从这 l 个元素中取出其中 r 个元素,与先无序取出 r 个元素,再从剩余的 n−r 个元素中无序取出 l−r 个元素是等效的。
- Cn0+Cn1+⋯Cnn=2n
对于 n 个互异元素,将其每种选择数相加,就是选取任意个元素的情况,对应到每个元素只有选和不选两种情况。
- Cn0−Cn1+Cn2−⋯=0
在杨辉三角中,第 n 行每个排偶数位的元素相加等于第 n−1 行元素每个元素相加,且每个排奇数位的元素相加也等于第 n−1 行元素每个元素相加。
- Crr+Cr+1r+⋯+Cnr=Cn+1r+1
同样可以反复套用第二个性质。
- (1+x)n=Σk=0nCnkxn−k=Σk=0nCnkxk
二项式展开: (x+y)n=Σi=0nCnixn−iyi ,证明可用数学归纳法
- Σi=0nCni2=C2nn
Σi=0nCni2=Σi=0nCni×Cnn−i 即等于 C2nn 。
组合数取模
-
目标:求出 Cnm≡?(modk)
-
情况一: k=1 太过于麻烦,跳过
-
情况二: k>1,nm≤107
使用组合数递推公式求并每步取模,时间复杂度 O(nm) 。
- 情况三: n≤109,m≤104,k≤109
核心要点:将 Cnm 写为 m!n(n−1)⋯(n−m+1) ,上下相除最多只用计算 O(m) 项。
对上下每一项进行质因数分解,然后统计每个质因子出现个数,快速幂合并。
- 情况四: n,m≤1010,k为小质数
Lucas 定理(下文将讲)。
- 情况五: n,m≤109,k≤105
扩展 Lucas 定理(下文也将讲)。
Lucas 定理
对于求 Cnm mod k 的值,一种方法是将 n 和 m 分别变为 k 进制的 t 位数 n1,n2,⋯,nt 与 m1,m2,⋯,mt ,位数不足的用前导零补足。 Cnm mod k 就等于对这两个数的 k 进制逐位求组合数相乘再取模。
即 Cnm≡Cn1m1⋅Cn2m2⋯Cntmt(modk) 。
扩展 Lucas 定理
将 k 质因数分解为 p1r1⋅p2r2⋯ptrt ,计算每一个 Cnm mod piri ,最后用中国剩余定理合并。
如何求 Cnm mod pk 呢?
先将 Cnm 写为 m!(n−m)!n! ,则可以将这里面每个阶乘都写为 pr⋅z 的形式,原式的值就很好求了。
对于质数 p ,有 n!=pr⋅z ,所以可以把这 pr 个数写出来,将每个 pr 的因子都提出来,剩下的数得到一个新的序列:
fac=1,2,⋯,p−1,1,p+1,p+2,⋯,2p−1,2,2p+1,2p+2,⋯,pr−1,1
同时还可以记录当前数贡献了几个 pr 的因子,对应上序列为:
num=0,0,⋯,0,1,0,0,⋯,0,1,0,0,⋯,0,r
则显然 i!=fac[i]⋅pnum[i] ,若 n≤pr ,则 n! 可以直接查表求出。
当 n>pr 时,将 pr+1,pr+2,⋯,2pr 的 pr 的因子提出来可以得到以下序列:
1,2,⋯,p−1,1,p+1,p+2,⋯,2p−1,2,2p+1,2p+2,⋯,pr−1,2
观察这个序列可以发现这个序列与序列 fac 只差最后一个数,所以对于 (i−1)⋅pr+1 到 i⋅pr 这个序列提出 pr 的因子后 ,最后一个数显然等于 i 。
如果只观察所有段序列的最后一个数,显然还需要计算 ⌊prn⌋! ,这就回到了之前的问题,所以可以通过递归的形式求解 n!。
所以我们可以通过这种方法求出 n!,m!,(n−m)! 的值分别为 x1⋅py1,x2⋅py2,x3⋅py3 ,则:
Cnm mod pr=x2⋅x3x1⋅py1−y2−y3 mod pr