跳转至

排列组合

引入

排列组合是组合数学中的基础。排列就是指从给定个数的元素中取出指定个数的元素进行排序;组合则是指从给定个数的元素中仅仅取出指定个数的元素,不考虑排序。排列组合的中心问题是研究给定要求的排列和组合可能出现的情况总数。排列组合与古典概率论关系密切。

在高中初等数学中,排列组合多是利用列表、枚举等方法解题。

加法 & 乘法原理

加法原理

完成一个工程可以有 n 类办法,ai(1in) 代表第 i 类方法的数目。那么完成这件事共有 S=a1+a2++an 种不同的方法。

乘法原理

完成一个工程需要分 n 个步骤,ai(1in) 代表第 i 个步骤的不同方法数目。那么完成这件事共有 S=a1×a2××an 种不同的方法。

排列与组合基础

排列数

n 个不同元素中,任取 mmnmn 均为自然数,下同)个元素按照一定的顺序排成一列,叫做从 n 个不同元素中取出 m 个元素的一个排列;从 n 个不同元素中取出 m(mn) 个元素的所有排列的个数,叫做从 n 个不同元素中取出 m 个元素的排列数,用符号 Anm(或者是 Pnm)表示。

排列的计算公式如下:

Anm=n(n1)(n2)(nm+1)=n!(nm)!

n! 代表 n 的阶乘,即 6!=1×2×3×4×5×6

公式可以这样理解:n 个人选 m 个来排队 (mn)。第一个位置可以选 n 个,第二位置可以选 n1 个,以此类推,第 m 个(最后一个)可以选 nm+1 个,得:

Anm=n(n1)(n2)(nm+1)=n!(nm)!

全排列:n 个人全部来排队,队长为 n。第一个位置可以选 n 个,第二位置可以选 n1 个,以此类推得:

Ann=n(n1)(n2)3×2×1=n!

全排列是排列数的一个特殊情况。

组合数

n 个不同元素中,任取 mn 个元素组成一个集合,叫做从 n 个不同元素中取出 m 个元素的一个组合;从 n 个不同元素中取出 mn 个元素的所有组合的个数,叫做从 n 个不同元素中取出 m 个元素的组合数,用符号 (nm) 来表示,读作「nm」。

组合数计算公式

(nm)=Anmm!=n!m!(nm)!

如何理解上述公式?我们考虑 n 个人选 m 个出来(mn),不排队,不在乎顺序。如果在乎顺序那么就是 Anm,如果不在乎那么就要除掉重复,那么重复了多少?同样选出来的 m 个人,他们还要「全排」得 m!,所以得:

(nm)×m!=Anm(nm)=Anmm!=n!m!(nm)!

组合数也常用 Cnm 表示,即 Cnm=(nm)。现在数学界普遍采用 (nm) 的记号而非 Cnm

组合数也被称为「二项式系数」,下文二项式定理将会阐述其中的联系。

特别地,规定当 m>n 时,Anm=(nm)=0

插板法

插板法(Stars and bars)是用于求一类给相同元素分组的方案数的一种技巧,也可以用于求一类线性不定方程的解的组数。

正整数和的数目

问题一:现有 n完全相同 的元素,要求将其分为 k 组,保证每组至少有一个元素,一共有多少种分法?

考虑拿 k1 块板子插入到 n 个元素两两形成的 n1 个空里面。

因为元素是完全相同的,所以答案就是 (n1k1)

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

非负整数和的数目

问题二:如果问题变化一下,每组允许为空呢?

显然此时没法直接插板了,因为有可能出现很多块板子插到一个空里面的情况,非常不好计算。

我们考虑创造条件转化成有限制的问题一,先借 k 个元素过来,在这 n+k 个元素形成的 n+k1 个空里面插板,答案为

(n+k1k1)=(n+k1n)

虽然不是直接求的原问题,但这个式子就是原问题的答案,可以这么理解:

开头我们借来了 k 个元素,用于保证每组至少有一个元素,插完板之后再把这 k 个借来的元素从 k 组里面拿走。因为元素是相同的,所以转化过的情况和转化前的情况可以一一对应,答案也就是相等的。

由此可以推导出插板法的公式:(n+k1n)

本质是求 x1+x2++xk=n 的非负整数解的组数(即要求 xi0)。

不同下界整数和的数目

问题三:如果再扩展一步,要求对于第 i 组,至少要分到 ai,ain 个元素呢?

本质是求 x1+x2++xk=n 的解的数目,其中 xiai

类比无限制的情况,我们借 ai 个元素过来,保证第 i 组至少能分到 ai 个。也就是令

xi=xiai

得到新方程:

(x1+a1)+(x2+a2)++(xk+ak)=nx1+x2++xk=na1a2akx1+x2++xk=nai

其中

xi0

然后问题三就转化成了问题二,直接用插板法公式得到答案为

(nai+k1nai)

不相邻的排列

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

二项式定理

在进入排列组合进阶篇之前,我们先介绍一个与组合数密切相关的定理——二项式定理。

二项式定理阐明了一个展开式的系数:

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

证明可以采用数学归纳法,利用 (nk)+(nk1)=(n+1k) 做归纳。

二项式定理也可以很容易扩展为多项式的形式:

n 为正整数,xi 为实数,

(x1+x2++xt)n=n1++nt=n(nn1,n2,,nt)x1n1x2n2xtnt

其中的 (nn1,n2,,nt) 是多项式系数,它的性质也很相似:

(nn1,n2,,nt)=tn

排列与组合进阶篇

接下来我们介绍一些排列组合的变种。

多重集的排列数 | 多重组合数

请大家一定要区分 多重组合数多重集的组合数!两者是完全不同的概念!

多重集是指包含重复元素的广义集合。设 S={n1a1,n2a2,,nkak} 表示由 n1a1n2a2,…,nkak 组成的多重集,S 的全排列个数为

n!i=1kni!=n!n1!n2!nk!

相当于把相同元素的排列数除掉了。具体地,你可以认为你有 k 种不一样的球,每种球的个数分别是 n1,n2,,nk,且 n=n1+n2++nk。这 n 个球的全排列数就是 多重集的排列数。多重集的排列数常被称作 多重组合数。我们可以用多重组合数的符号表示上式:

(nn1,n2,,nk)=n!i=1kni!

可以看出,(nm) 等价于 (nm,nm),只不过后者较为繁琐,因而不采用。

多重集的组合数 1

S={n1a1,n2a2,,nkak} 表示由 n1a1n2a2,…,nkak 组成的多重集。那么对于整数 r(r<ni,i[1,k]),从 S 中选择 r 个元素组成一个多重集的方案数就是 多重集的组合数。这个问题等价于 x1+x2++xk=r 的非负整数解的数目,可以用插板法解决,答案为

(r+k1k1)

多重集的组合数 2

考虑这个问题:设 S={n1a1,n2a2,,nkak,} 表示由 n1a1n2a2,…,nkak 组成的多重集。那么对于正整数 r,从 S 中选择 r 个元素组成一个多重集的方案数。

这样就限制了每种元素的取的个数。同样的,我们可以把这个问题转化为带限制的线性方程求解:

i[1,k], xini, i=1kxi=r

于是很自然地想到了容斥原理。容斥的模型如下:

  1. 全集:i=1kxi=r 的非负整数解。
  2. 属性:xini

于是设满足属性 i 的集合是 SiSi 表示不满足属性 i 的集合,即满足 xini+1 的集合(转化为上面插板法的问题三)。那么答案即为

|i=1kSi|=|U||i=1kSi|

根据容斥原理,有:

|i=1kSi|=i|Si|i,j|SiSj|+i,j,k|SiSjSk|+(1)k1|i=1kSi|=i(k+rni2k1)i,j(k+rninj3k1)+i,j,k(k+rninjnk4k1)+(1)k1(k+ri=1knik1k1)

拿全集 |U|=(k+r1k1) 减去上式,得到多重集的组合数

Ans=p=0k(1)pA(k+r1AnAipk1)

其中 A 是充当枚举子集的作用,满足 |A|=p, Ai<Ai+1

圆排列

n 个人全部来围成一圈,所有的排列数记为 Qnn。考虑其中已经排好的一圈,从不同位置断开,又变成不同的队列。 所以有

Qnn×n=AnnQn=Annn=(n1)!

由此可知部分圆排列的公式:

Qnr=Anrr=n!r×(nr)!

组合数性质 | 二项式推论

由于组合数在 OI 中十分重要,因此在此介绍一些组合数的性质。

(1)(nm)=(nnm)

相当于将选出的集合对全集取补集,故数值不变。(对称性)

(2)(nk)=nk(n1k1)

由定义导出的递推式。

(3)(nm)=(n1m)+(n1m1)

组合数的递推式(杨辉三角的公式表达)。我们可以利用这个式子,在 O(n2) 的复杂度下推导组合数。

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

这是二项式定理的特殊情况。取 a=b=1 就得到上式。

(5)i=0n(1)i(ni)=[n=0]

二项式定理的另一种特殊情况,可取 a=1,b=1。式子的特殊情况是取 n=0 时答案为 1

(6)i=0m(ni)(mki)=(m+nk)

拆组合数的式子,在处理某些数据结构题时会用到。被称为 范德蒙恒等式

(7)i=0n(ni)2=(2nn)

这是 (6) 的特殊情况,取 n=k=m 即可。

(8)i=0ni(ni)=n2n1

带权和的一个式子,通过对 (3) 对应的多项式函数求导可以得证。

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

与上式类似,可以通过对多项式函数求导证明。

(10)l=0n(lk)=(n+1k+1)

通过组合分析一一考虑 S={a1,a2,,an+1}k+1 子集数可以得证,在恒等式证明中比较常用。被称为 朱世杰恒等式

(11)(nr)(rk)=(nk)(nkrk)

通过定义可以证明。

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

其中 F 是斐波那契数列。

(13)(n+kk)2=j=0k(kj)2(n+2kj2k)

通过 (6) 可以证明。被称为 李善兰恒等式

二项式反演

fn 表示恰好使用 n 个不同元素形成特定结构的方案数,gn 表示从 n 个不同元素中选出 i0 个元素形成特定结构的总方案数。

若已知 fngn,那么显然有:

gn=i=0n(ni)fi

若已知 gnfn,那么:

fn=i=0n(ni)(1)nigi

上述已知 gnfn 的过程,就称为 二项式反演

证明

将反演公式的 gi 展开得到:

fn=i=0n(ni)(1)ni[j=0i(ij)fj]=i=0nj=0i(ni)(ij)(1)nifj

先枚举 j,再枚举 i,得到:

fn=j=0ni=jn(ni)(ij)(1)nifj=j=0nfji=jn(ni)(ij)(1)ni

使用 「组合数性质 | 二项式推论」 的公式 (11) 得到:

fn=j=0nfji=jn(nj)(njij)(1)ni=j=0n(nj)fji=jn(njij)(1)ni

k=ij。则 i=k+j,上式转换为:

fn=j=0n(nj)fjk=0nj(njk)(1)njk1k

使用 「组合数性质 | 二项式推论」 的公式 (5) 得到:

fn=j=0n(nj)fj[n=j]=fn

证毕。