生成函数入门
生成函数入门
普通型生成函数
定义
将序列\(A\)表示为形式幂级数\(A(x)=\sum\limits_{i=0}^na_ix^i\) ,则称形式幂级数\(A(x)\)为序列\(A\) 的普通型生成函数,形式幂级数的第\(i\) 项系数就是序列A的第\(i\)项。
初学会有一个疑问,什么是形式幂级数?顾名思义,这个幂级数中的\(x\)只是一个形式而已,\(x\)可以取任意值而不影响我们需要得到的系数的值(因为我们用生成函数需要的只是系数\(a\),而和\(x\)无关)所以为了化简形式幂级数的表达,我们常常定义\(|x|<1\),这样我们的和式就是收敛的。
比如序列\(<1,1,1,1,1,...>\) 的普通型生成函数就是\(\sum\limits_{i=0}^{\infty}x^i=1+x+x^2+x^3+x^4+...\) ,如果\(|x|<1\) ,那么我们会得到和式的值\(\sum\limits_{i=0}^{\infty}x^i=\frac{1}{1-x}\),可以用右边的值来简单的表达一个序列的生成函数。
应用
使用普通型生成函数主要是为了解决通过两个序列得到一个新序列的问题。
经典的例子:
有n种不同的球,现在任意选择k个球,问有多少个方案?
初看这个问题,接触过的人容易联想到将问题转换为不定方程的形式,即问:
\(x_1+x_2+...+x_n=k,0\le x\) 的解的个数
考虑将\(x\) 映射到\(y=x+1\) 上,把方程转换为\(y_1+y_2+y_3+...+y_n=k+n,1\le y\) ,然后就是一个\(k+n\)个小球插\(n-1\) 个板子有多少种插法的问题了,答案就是 \(\binom{k+n-1}{n-1}\) 。
而这个问题也可以通过生成函数来求解。每一种球的生成函数是\(\sum\limits_{i=0}^{\infty}x^i=\frac{1}{1-x}\),我们考虑只有两种球,从中挑出3个球的方案。
它的挑选方式是(0,3) ,(1,2),(2,1),(3,0)共四种,假设两个球的生成函数序列是A(x),B(x),那么我们认为这里边的第一种方案是A(x)的第0项和B(x)的第4项组合来的,同理,第二种方案是A(x)的第1项和B(x)的第3项组合来的,形式化的,如果我们设最终选k个球的方案序列是C,那么C的生成函数是\(\sum\limits_{i=0}c_ix^i\),而我们刚刚的例子可以表示为\(c_3=\sum\limits_{i=0}^{3}a_ib_{3-i}\) ,(A ,B都是全1序列),也就是说我们C的生成函数应该是我们A的生成函数和B的生成函数的卷积,即A(x)B(x)=C(x),表达式即:
\(C(x)=\sum\limits_{i=0}^{\infty}x^i\sum\limits_{j=0}^{i}a_jb_{i-j}\) , 每一项系数\(c_i\)都是两个生成函数在\(i\)的卷积。
那如果是3种球呢?就得三个一起卷? 4种呢?太麻烦了吧。
对于这道题来说似乎确实是这样,单纯考虑生成函数是困难的,或者说复杂度是较高的,但是,这道题指明了普通型生成函数的一个应用,那就是对于知n求一的这种问题,可以考虑把序列生成函数卷积,然后就可以在第n次项的系数找到问题的解。
且这个例子指明了一个事实:考虑把A(x)表示为\(\frac{1}{1-x}\),B(x)同理,那它们的卷积是\(\frac{1}{(1-x)^2}\),即\(C_2(x)=\frac{1}{(1-x)^2}\),而我们也知道\(C_n(x)=\sum\limits_{i=0}^{\infty}\binom{n+i-1}{i-1}x^i\),(C的下标表示我们球的种类数量),所以我们可以发现\(\frac{1}{(1-x)^n}=\sum\limits_{i=0}^{\infty}\binom{n+i-1}{i-1}x^i\),即\(n\)种球,选任意个球的方案的序列的生成函数和它的和我们能够将其对应起来了,方便我们对生成函数的应用。
以上,我们介绍了普通型生成函数如何处理简单的组合问题。
指数型生成函数
定义
同样定义序列A的生成函数,但是这次我们换了个方式,我们定义A的生成函数为\(A(x)=\sum\limits_{i=0}^{\infty}a_i\frac{x^i}{i!}\),并称这样定义的生成函数为指数型生成函数。
应用
指数型生成函数用来解决排列问题。
问,从n种球中依次拿出\(k_1,k_2,k_3...k_n\)共N个球形成排列,有多少种方案?
(即可以认为一种球代表一个数字,这样有序的取N个数字有多少给排列,这种问题也叫多重集的排列问题)
这个问题从排列组合的角度也比较好解决,考虑总序列的排列方式\(N!\),然后除去所有的相同数字的内部排列
最终的方案就是 \(\frac{N!}{k_1!k_2!k_3!...k_n!}\),如果只是问从n组数中得到N个球的排列方案,就要把下边的k进行组合,然后把所有的方案加起来,也就是
\(\sum\limits_{k_1=0}^{N}\sum\limits_{k_2=0}^{N-k_1}\sum\limits_{k_3=0}^{N-k_1-k_2}...\sum\limits_{k_{n-1}=0}^{N-\sum_1^{n-2}k_i}\frac{N!}{k_1!k_2!...(N-\sum_1^{n-1}k_i)!} \ \ \ (1)\) 这样的一个式子。
我们尝试用生成函数来解决这个问题,设每一个数字的生成函数都为\(\sum\limits_{i=0}^{\infty}\frac{x^i}{i!}\)。
测试一组小数据 n=3,N=3,我们看看\(A_1(x)* A_2(x) *A_3(x)\),在第3项的系数。
第3项的系数为\(\frac{9}{2}\)我们把它乘上一个\(3!\),那么我们就会得到值\(27\),即在3种数里选择3个的排列方案了。
不信?我们暴力算一遍,选择为\((3,0,0)\) (即第一种选3个,第二种选0个,第三种选0个,后同),排列为1
\((0,3,0)=1,(0,0,3)=1,(2,1,0)=3,(2,0,1)=3,(1,2,0)=3,(1,1,1)=6,(1,0,2)=3,(0,2,1)=3,(0,1,2)=3\)
他们的和\(1+1+1+3+3+3+6+3+3+3=27\) ,正是27!(是27不是27!)
我们考虑为什么我们的生成函数卷积得到的系数乘上一个\(N!\)就是我们想要的选N个数的答案,观察我们的(1)式,它需要的就是所有情况的组合阶乘作为每个情况的分母,而我们的生成函数卷积,\(x\)的指数就意味着选择的数的数量,我们知道,为了产生第n项的系数(x的指数为n),我们会进行所有可能的组合相乘,卷积后的系数正是所有的选择产生的和,分母刚好就是我们(1)式中\((k_1!k_2!...k_n!)\),所以我们距离正确答案就差乘上一个分子N!,因此我们得到的卷积后得到的系数只要乘N!,就是我们想要的答案。
同样,我们如果把指数型生成函数的\(x\)划定在\(|x|<1\)的范围内,也会得到一个漂亮的收敛值\(e^x=\sum\limits_{i=0}^{\infty}\frac{x^i}{i!}\)(泰勒展开),它也可以方便我们的应用。
上边说过的两个式子\(\frac{1}{(1-x)^n}=\sum\limits_{i=0}^{\infty}\binom{n+i-1}{i-1}x^i\) ,\(e^x=\sum\limits_{i=0}^{\infty}\frac{x^i}{i!}\)确实非常有用,但这里只是入门的理解,所以就不在这个博客里展开了(其实我现在也不大会用,但能用的地方确实多!!),下边会做题用的。
写这个博客主要为了自己复习以及加深对生成函数的理解,如有不当,请不吝赐教。
参考资料
《小学生都能看懂的生成函数从入门到升天教程》《生成函数全家桶》
[算法|小学生都能看懂的生成函数入门教程 - 知乎 (zhihu.com)]