引言
组合计数问题是信息学竞赛中常见的一类问题,而生成函数往往是解决这类问题的重要工具。
上面这句话出自2015年金策的论文,这篇论文写的非常系统,推荐阅读。
本文则是偏向于推导和总结,分成组合数学部分和多项式全家桶 一点都不全 部分,分别讲解生成函数在解决组合计数问题的方法及技巧。
组合数学
概念
生成函数
生成函数就是一列用来展示一串数字的挂衣架。(赫伯特·维尔夫)
在数学中,某个序列 ({displaystyle (a_{n})_{nin mathbb {N} }}) 的母函数(又称生成函数,英语:Generating function)是一种形式幂级数,其每一项系数可以提供关于这个序列的信息。使用母函数解决问题的方法称为母函数方法。(维基百科)
看完上面的解释,相信初次接触生成函数的读者也对它有了一定的了解 (扯吧 。生成函数按实现功能可以分成两类:普通型生成函数、指数型生成函数。
普通型生成函数(OGF)
对于一个给定的数列 ({a_n}) ,定义它的普通型生成函数 (G(x)) 为
如果这个数列是不是无穷数列,那么比最后一项高的项都为 (0) 。
指数型生成函数(EGF)
对于一个给定的数列 ({a_n}) ,定义它的指数型生成函数 (G(x)) 为
如果这个数列是不是无穷数列,那么比最后一项高的项都为 (0) 。
生成函数说白了就是把一个数列摆在一个形式幂级数上,而形式幂级数就是上面那个写成函数样子的 (G(x)) ,注意,它真的就只是一个形式,那个变量 (x) 不可能真的带一个数进去算。如果拿挂衣架做比喻的话,那 (x) 的不同幂次就相当于挂衣架上的一个一个钩子,数列 ({a_n}) 就是一件一件的衣服。钩子把一件一件衣服挂在挂衣架上,就是生成函数。
我们不妨用几道烂大街的数学题来看一下生成函数这个东西的作用。
例题
- (例题 1-1-1)有 (1g) 砝码 (2) 枚,(2g) 砝码 (3) 枚,(3g) 砝码一枚,相同质量砝码之间没有区别,问称出每种质量的方案数。
考虑生成函数,设 (x) 的指数为砝码的质量和,(F(x)) 为每种质量和的方案数的普通型生成函数,则
其中每一个括号里的内容代表取每一种质量的砝码的情况,以第一个括号为例,(1)(即 (x^0) )代表不取 (1g)
砝码,(x) 代表取 (1) 个 (1g) 砝码,(x^2) 代表取 (2) 个 (1g) 砝码。可以看出,生成函数的加法运算代表着“或”,而乘法运算则代表着“与”。
- (例题 1-1-2)你有数字 (1) 两个,数字 (2) 三个, 数字 (3) 一个,问选出一个、两个、三个……数字的方案数。
考虑生成函数,设 (x) 的指数为选出数字的个数,(F(x)) 为的不同个数的方案数的普通型生成函数,则
本题的题面和上道题有点像,但是要求的东西不同,上道题要求的是每种质量和的方案数(即数字总和),而这道题是数字个数,定义状态不同,故生成函数不同。
- (例题 1-1-3)你有数字 (1) 两个,数字 (2) 三个, 数字 (3) 一个,问组成一位数、两位数、三位数……的方案数。
与上题的区别在于,位置有了标号,如 (123) 和 (132) 为不同的情况。考虑生成函数,设 (x) 的指数为数字的位数,(F(x)) 为的不同位数的方案数的指数型生成函数,则
指数型生成函数可能刚开始有点难以理解,初学者可能会发出这样的疑问:这个东西不就是 (x^n) 下面加了一个 (n!) 吗?是的,形式上就是这样的,在编程中,运算时也要把它转成普通型运算,再转成指数型展示。但是,与上面的问题对比一下,就不难发现一个规律:
普通型生成函数解决的是组合问题(无标号),指数型生成函数解决的是排列问题(有标号)。
这里面也没什么大道理,让我们观察其中一项的计算过程,以 (x^3) 为例,我们看一下那个 (19) 是怎么来的。
式子变一变,就变成了一个多重元素全排列的形式,例题 1-1-2 是对一样的数列构造一个普通型生成函数,([x^3]=6) ,(([x^n]) 表示取多项式中次数为 (n) 的项的系数)而 (displaystyle {19over 3!}) 展开也有 (6) 项,只是每一项多乘了排列数罢了。
更一般的说,设原题三个括号中的生成函数分别为 (A(x),B(x),C(x)),有
对于有标号的组合对象,我们在转移时还要考虑不同的标号排列,于是我们在分母上添了阶乘,这样就可以帮助我们转移了。接下来,我们来了解一下“组合对象”这一名词。
组合对象
组合计数问题一般定义了一类组合对象 (A) ,它可能是满足某一类性质的树、图、串等对象的集合;其中每个对象 (a in A) 都被赋予了一个大小 ({ m size}(a) inmathbb N),它可能代表节点数,序列长度等。对于某个固定的 (n),满足 ({ m size}(a)=n) 的对象是有限的,记作 (A_n) 。我们的任务通常为求出 (A_n) 的数值。
根据不同问题的要求,组合对象可以分为有标号和无标号两类。
(论文)
通过以 (A_n) 构造生成函数,我们得以将 ({ m size}(a)) 与 (x) 的指数对应,将 (A_{{ m size}(a)}) 与 (x) 的系数对应,从而求出我们想要的结果。
在例题 1-1-1 中,不同砝码组合构成的集合就是我们要研究的组合对象,每一种砝码组合就是一个对象,对象 (a) 的 ( m size) 定义为这个砝码组合的质量和,(A_n) 表示的称出的质量和为 (n) 的方案数,该组合对象属于无标号组合对象;
在例题 1-1-3 中,不同 (n) 位数( (n) 个数字的排列)构成的集合就是我们的组合对象,一个 (n) 位数就是一个对象,对象 (a) 的 ( m size) 定义为数的位数,(A_n) 表示构成 (n) 位数的方案数,该组合对象属于有标号组合对象。
公式
仅仅只是表示成几个式子的乘积只是生成函数最基本的部分,利用形式幂级数的变形进行推导才是比较有研究价值的地方,接下来,我们来展示一些基础而重要的公式。
- 公式 ( m I)
也被称作无穷递缩等比数列求和公式,由于收敛性,(xin(0,1)) 时式子成立,但由于本文讲的是生成函数,写出来的式子是形式幂级数,所以 (x) 不能代具体的数。
把左边的分母乘到右边去就可以得证,或者直接套用等比数列求和公式证明。
- 公式 ( m II)
可以由公式 ({ m I}) 两边同求 (k-1) 次导,再同除以 ((k-1)!) 得到。 也可以把式子转化为 ({ig(}(1-x)^{-1}{ig)}^k) ,用组合方法证明。
- 公式 ( m{III}) (广义二项式定理)
其中 (displaystyle{alpha choose k}={alpha(alpha - 1)cdots(alpha - k + 1)over k!}={alpha^{{underline k}}over k!})
可以利用广义二项式定理推导公式 ( m{I}) 和公式 ( m{II}) 。
- 公式 ( m{IV}) (泰勒展开)
表示 (f(x)) 在 (x=a) 处的泰勒展开,其中 (f^{(n)}) 表示 (f) 的 (n) 阶导函数,其中 (a=0) 的情况被称作麦克劳林展开,形式如下:
- 公式 ( m V)
直接套用麦克劳林展开公式就可以得到,注意 (e^x) 的导数是它本身。
应用
接下来,我们来详细讲讲生成函数的应用,包括但不限于排列组合问题。
基础构造
在证明某些恒等式,或求某些数列的通项的时候,我们可以构造生成函数来解决。
- (例题 2-1-1)证明 (displaystyle sum_{i=0}^k{nchoose i}{mchoose k-i}={n+mchoose k})
上式即为范德蒙德卷积式。我们利用组合意义可以很容易得到证明,即在 (n) 个元素中选 (i) 个,在 (m) 个元素中选 (k-i) 个,当 (i) 取任意值时,这个方案数显然等于在 (n+m) 个元素中选 (k) 个。我们也可以用生成函数更加直观的表达上述组合意义,从而加以理性证明。
对于 (n+m) 个物品,设 (x) 的指数为选出物品的个数,(F(x)) 为每种个数的方案数的普通型生成函数。分别从 (n) 个物品和 (m) 个物品中选,我们有以下式子
而将 (n+m) 个物品当作整体,我们有以下式子
对照两式可得 (displaystyle sum_{i=0}^k{nchoose i}{mchoose k-i}={n+mchoose k}),即原命题得证。
其实对于本题,我们也可以不考虑组合意义,直接由 ((1+x)^ncdot(1+x)^m=(1+x)^{n+m}) 这条等式,两边分别二项式展开证得所求结论。
- (例题 2-1-2)证明 (displaystyle sum_{i=0}^n(-1)^i{nchoose i}^2= egin{cases}displaystyle 0&n为奇数\displaystyle(-1)^{nover 2}{nchoose {nover 2}}&n为偶数end{cases})
这题不好看出其组合意义,但是求证的表达式和上题很相似,如果将原式看成 (displaystyle sum_{i=0}^n(-1)^i{n choose i}{nchoose n-i}),那么便很像范德蒙德卷积式了。类似的,我们设 (F(x)=(1-x)^ncdot(1+x)^n=(1-x^2)^n)。
在上式中取 (k=n),下式中取 (displaystyle k={nover 2}) 即可得出结论。