あいさか たいがblogAisaka_Taiga的博客
//https://img2018.cnblogs.com/blog/1646268/201908/1646268-20190806114008215-138720377.jpg

组合数学入门

Toretto·2023-05-20 22:29·262 次阅读

组合数学入门

排列组合

排列就是指从给定个数的元素中取出指定个数的元素进行排序;组合则是指从给定个数的元素中仅仅取出指定个数的元素,不考虑排序。--------OI Wiki

乘法原理和加法原理#

加法原理,就好比一个工作,有 n 个解决的方案,第 i 项方案有 ai 种不同的实现方式,所以这个工作有 a1+a2+a3++an 种方式来解决。

乘法原理,就好比一个工作,有 n 个步骤,第 i 步有 ai 种方法来完成,所以这个工作的方式有 a1×a2×a3××an 种方式来解决。

排列数#

给定 n 个数,从中选取 m 个数形成一个排列,可能的排列的数量,用 Anm 来表示(给定的数都为正整数)。

排列的计算公式:

Anm=n×(n1)×(n2)××(nm+1)=n!(nm)!,n,mNmn

其实就是分子分母同乘一个 (nm)!

其中 n!=1×2×3××n

全排列就是当 n=m 的时候的一种特殊情况,此时 Ann=n!

组合数#

区别就是,排列数是要求顺序的,而组合数是从 n 个元素里面选取 m 个数组成一个集合,问有多少种可能,通常用 Cnm 来表示。

组合数计算公式:

Cnm=n!m!(nm)!

可以发现只比排列的公式分母多了一个 m!,因为不考虑顺序,所以可以想到,挑出来的 m 个元素组成的集合,里面的排列数是 m!,而这里面的元素组成的集合都是相同的,也就是这 m 个数本来应该算一个,但是排列里面是算了 m!,所以排列的公式除以 m! 即为我们要求的答案。

现在人们习惯用 (nm) 表示 n 个元素里面选 m 个,但是我个人觉得不如用 Cnm 直观,但我们还是要了解这个表示方式。

插板法#

为什么叫插板法呢,因为他是用于解决把一些相同种类的元素分成不同的几组的一种方式, n 个元素分成 k 组,每一组至少有一个元素,就相当于拿 k1 个板子放到 n1 个空里,故因此而得名。

因为元素是完全相同的,所以我们根据上面的组合数可以得出公式:

(n1k1)

本质是求 x1+x2++xk=n 的正整数解的组数。

改一下题目,如果要是允许有空的组呢?

如果这样的话,直接插板是不行的,因为有可能出现一堆板子都插到一个空隙里,这样的话求组合数就是错误的了。

所以我们先借来 k 个元素,在这 n+k1 个空隙里插板,保证我们的每一组里面都是至少有 1 个元素,这样我们就把这个问题转化成了上一个问题,我们也可以得出公式:

(n+k1k1)=(n+k1n)

可以想象一下,我们是先借了 k 个元素来保证我们的每一组里面都至少有一个元素,那么我们就按照第一个问题一样求解,最后把所有的板子都拿走,那么答案是不会有所变化的。

本质上是求 x1+x2++xk=n 的非负整数解的组数。

我们来加一些限制:如果说对于第 i 组我们需要至少分到 ai 个元素,ain,我们又该怎么去求解呢?

和上面一样,本质上就是求 x1+x2++xk=nxiai 的解的组数。

我们浅想一下,设 xi=xiai,所以 xi=xi+ai,那么我们要求的就是:

(x1+a1)+(x2+a2)++(xk+ak)=n

x1+x2++xk=na1a2ak

x1+x2++xk=nai

那么我们知道 xi 是一个非负的整数,所以我们可以直接用问题二的公式:

(nai+k1nai)

1nn 个自然数选 k 个,这 k 个数种任何两个数都不相邻的组合有 (nk+1k) 种。

二项式定理#

二项式就是由两项组成的式子,比如 2x 是一项式,2x+3y 是二项式,2x+3y+4z 是三项式,以此类推。

主要是用来解决 (a+b)n 的完全展开式的问题,其实是有规律可循的,我们可以通过这个定理快速获得第 i 项。

举一个最常见的例子:初中的完全平方公式 (a+b)2=a2+2ab+b2

或者高中的完全立方公式 (a+b)3=a3+3a2b+3ab3+b3

相信你已经发现了他们系数的规律,那就是杨辉三角其实就是用来解释 (a+b)n 的各项的系数才有的杨辉三角,这个东西很奇妙,我们后面会提到他和组合数的关系。

image
公式就是

(a+b)n=i=0n(ni)anibi

为什么呢,你可以考虑一下,我们在推导完全立方公式的时候,我们是一项一项暴力拆开成 n(a+b) 相乘然后拆开合并的同类项,那么我们暴力拆一下可以知道,每一项都是从 n(a+b) 中选 a 或者 b 相乘得到的,也就是说,我们可以把展开后的第 i 项看作是选了 ianib 然后相乘得到的,而这样的组合方案是 (ni),所以我们得到展开后第 i 项就是 (ni)anibi ,累加后就得到了上面的公式。

组合数性质#

下面挑几个会的证明一下,不会的先咕了。

  1. (nm)=(nnm)

证明:

(nnm)=n![n(nm)]!(nm)!=n!m!(nm)!=(nm)

  1. (nk)=nk(n1k1)

  2. (nm)=(n1m)+(n1m1)

证明:从 n 个数里面选 m 个数,就等同于第一个数选了,然后从 n1 个中选 m1 个数和第一个数没选,从 n1 个数中选 m 个数的方案的和。或者你可以看看杨辉三角

  1. (n0)+(n1)++(nn)=i=0n(ni)=2n

  2. i=0n(1)n(ni)=[n=0]

证明:当 m 为奇数的时候,由性质 1 得,两项一一对应和为 0 ,显然成立;当 m 为偶数的时候,利用 (n0)=(n10),(mm)=(m1m1) 替换,再用递推式得到:

i=0n(1)i(ni)=(n0)(n1)+(n2)(nn1)+(nn)

=(n10)(n1)+(nn1)+(nn)

=(n10)((n10)+(n11))+((n1n2)+(n1n1))+(n1n1)=0

  1. i=0m(ni)(mmi)=(n+mm)(nm)

证明:

(n+m) 个数中选 r 个数,在前 n 个中选 i 个数的方案有 (ni) 种,在后 m 个里选 (ri) 个数的方案数为 (mri) 种,相乘求和即可得到

(n+mr)=i=0r(ni)(mri)

一开始的式子就是这个式子的 r=m 的情况。

  1. i=0n(ni)2=(2nn)

证明:其实是 6 的特殊情况,取 n=m 即可。

  1. i=0ni(ni)=n2n1

证明:把左边拆开得到:

=i=0nn!(ni)!(i1)!

=n×i=0n(n1)!(ni)!(i1)!

=n×i=0n(n1i1)

=n×i=0n1(n1i)=n×2n1

  1. i=0ni2(ni)=n(n+1)2n2

证明:和性质 8 类似,先不证了。

  1. i=0n(ik)=(n+1k+1)

  2. (nr)(rk)=(nk)(nkrk)

证明:

(nr)×(rk)=n!r!(nr)!×r!k!(rk)!

=n!k!(nr)!(rk)!

分子与分母同乘 (nk)!

n!k!(nk)!×(nk)!(rk)!(nr)!=(nk)×(nkrk)

  1. i=0n(nii)=Fn+1

  2. (n+m+1m)=i=0m(n+ii)

证明:首先对性质 3 变形:(nm)+(nm1)=(n+1m),并且我们知道 (n0)=(n+10)=1,那么就有:

i=0m(n+ii)=(n0)+(n+11)++(n+mm)

=(n+10)+(n+11)++(n+mm)

=(n+21)+(n+22)++(n+mm)

最后就会得到:

=(n+m+1n)

其中 F 指斐波那契数列,[n=0] 表示如果 n0 则值为 1,反之值为 0

其实还有二项式反演啥的但是我咕了。

组合数取模#

有的时候我们题目里面会看到一些要求取模的那种问题。

当然我们都知道取模之后做除法是会出问题的,这个时候我们就需要结合逆元来做。

我们大致可以把这类问题分为三类:

一、1n,m1000p 为任意实数,显然我们可以利用组合数的性质 (nm)=(n1m)+(n1m1) 来递推,但很明显 O(n2) 的复杂度不足以让我们在数据范围更大的地方使用。

二、1n,m106p 为质数且 p>106O(n) 预处理 i!modp,然后用费马小定理,扩欧啥的搞一搞 m!(nm)! 的逆元一乘就好,询问是 O(logn) 的,当然也可以用线性求逆元直接 O(nlogn) 预处理 i!i! 的逆元,询问直接 O(1) 的:

Copy
ans=jc[n]*inv[m]*inv[n-m]%P;

三、若 p 为质数,1n,m1018,p105 ,这个时候用卢卡斯定理来解决,具体下面讲。

其中最常用的是第二种了,因为题目里一般的取模都是 1e9+7 之类的某大质数,而且 106 也足够了。

卢卡斯定理#

如上文所述,卢卡斯定理一般都是用于求解组合数取模。

上文中讲的,当 p<m 的时候,分母的乘法逆元是可能不存在的(m 可能是 p 的倍数),所以我们就要用到卢卡斯定理。

内容#

对于非负整数 n,m 和质数 p

(nm)(npmp)×(nmodpmmodp)(modp)

(或许你在其他地方看见的都没有这个乘号,我觉得打出来更清楚)

引理一#

对于组合数 (pi),其中 p 为质数,满足如下同余式子:

(pi)0(modp)(0<i<p)

首先我们由组合数的定义式可以知道:

(pi)=p!i!(pi)!

由于 0<i<p ,且 p 为质数,所以 i!(pi)! 都不可能是 p 的因子。又因为组合数一定是一个整数,所以 i!(p1)! 一定是 (p1)! 的因子,这样组合数就可以表示成:

(pi)=(p1)!i!(pi)!p=kp

等式两边模 p 得到:

(pi)0(modp)(0<i<p)

引理二#

对于整数 x 和素数 p,满足如下同余式:

(1+x)p(1+xp)modp

还记得我们之前的二项式定理吗,我们用它来对左边进行二项式展开,然后用引理一:

(1+x)p((pp)+(pp1)x++(p0)xp)

((pp)+(p0)xp)

(1+xp)modp

在第二步中将中间的多项都利用定理一给抹除了(因为模 p0 嘛)。

第三步中,因为 (pp)=(p0)=1 所以最后得到了这个式子。

证明#

对于组合数 (nm),将 nm 分别除上 p 得到商和余数,设:

n=sp+q(q<p)

m=tp+r(r<p)

(1+x)nmodp 转化成同余式:

(1+x)n(1+x)sp+q

((1+x)p)s(1+x)q

(1+xp)s(1+x)q

i=0s(ssi)xipi=0q(qqi)xi(modp)

第四步是用到了二项式定理。

或者:

(1+x)n(1+sxp++(ssi)xip++xsp)(1+qx++(qqi)xi++xq)(modp)

由于这里 x 为未知数,所以等式左侧的 xi 系数必然与等式右侧的系数 xi 的系数一致。

对于左侧 (1+x)n 中,xm 对应的系数为 (nnm)=(nm)=(sp+qtp+r)

对于右侧,xm=xtp+r=xtpxr,这有一种可能,即:

(sst)xtp×(qqr)xr

(sst)(qqr)=(st)(qr)

从而得到卢卡斯定理如下:

(nm)(sp+qtp+r)(st)(qr)(modp)

还可以表示成:

(nm)(npmp)(nmodpmmodp)(modp)

这样就把问题转化为了递归的问题,只要 np 时,我们就可以调用这个公式,将问题转化为 (nm)modp(n<p) 的问题,而 p105 时满足:n<p105

可以通过 O(n) 的复杂度计算出 n!modpinvn!modp,预处理完直接调用。

感谢OI Wiki以及bloodstalk的帮助

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