看了一个下午的生成函数(又称母函数),初次理解,于是便总结一下。
生成函数是说,构造一个多项式函数 g(x) ,是的 x 的n 次方 的系数是 f(n) .
即: ~g(x) = 1 + f(1) * x^1 + f(2) * x^2 + f(3) * x^3 + .......+f(k) * x^k + ........
这里的 g(x) 就是一个生成函数。
那么 f(n) 的含义呢?
这个函数的话,就是由你自己构造了。
如何构造呢?下面由一个例题,来引出:
用1,2,3来组成不同的值。而我们要求的就是给定一个n,有多少种组成的方法。
这里我们用到生成函数来解这题。
要用到生成函数就一定先要知道 f(n) 这个函数。
我们先来看这个问题,一个数 n 能用 1 组成的方法有多少种呢? 答案很明显,1种。
也就是说如果我们上面说的那个问题变成: 用 1 来组成不同的值,我们要求给定一个n ,有多少种组成的方法。
这样,这个问题是不是变得很简单了,只要不是脑残,应该都能一眼看出答案,1种,不管n 是多少,都是一种。
那么我们的 f(n) 也就出来了。
即: f(1)=1
f(2)=1
f(3)=1
f(4)=1
f(5)=1
......
f(n)=1
很容易就可以看出这个f()函数的意义,即n代表一个值,而f(n)的值表示用 1 组成 n的方法的个数。
既然f(n) 出来了,那么它的构造函数当然也出来了。
即:~g(x)=1+x^1+x^2+x^3+.........+x^k+.....x^n+.......
到这里,不着急,我们继续看,
刚才我们是用 1 来组成一个给定的任意值 n ,求组成的方法数。
现在我们继续转化,我们用 2 来组成一个给定的任意值 n, 求组成的方法数。
因为用2来组成的数一定都是偶数,而且组成的方法数也一定都是一种,所以
我们根据 f() 函数的定义,可以知道 f(n) 的值:
f(1)=0
f(2)=1
f(3)=0
f(4)=1
f(5)=0
......
这个的含义也和前一个问题的 f() 函数一样,那么我们的构造函数也能出来了。
即:~g(x)=1 + x^2 +x^4 +x^6+.......
同理我们也就可以推出,当用 3 来组成 n 时的 f()函数,以及生成函数。
那么接下来我们推广一下,我们将原来的 1 啊,2 啊, 3啊,等一个个的数,都看成是一个个的集合,即{1},{2},{3}
而我们的问题就是要用集合的里的数,来组成一个数值 n,求组成的方法数。
原先集合里都只有1个元素,所以我们能很快得出 f (n) 答案,但是当有多个元素时,这个问题,就变成了,我们最开始要求的那个问题了。
如何用1,2,3来组成一个数值 n,求组成的方法数。
这里的集合就是{1,2,3}
而结果如何求呢?
因为我们已经计算出了,单个元素的 f() 函数,所以我们求此时的集合所对应的 f() 函数时,就要用到构造函数。
我们将每个元素的构造函数都乘起来,得到的这个函数,就是我们现在的集合所对应的生成函数了。
即:g(x)=(1+x^1+x^2+.....) (1 + x^2 +x^4 +......) (1 + x^3 +x^6+ .......)
我们展开函数,使之成为
g(x) = 1 + f(1) * x^1 + f(2) * x^2 + f(3) * x^3 + .......+f(k) * x^k + ........
然后我们要求的结果也就出来了。就是 f(n) 。即:用{1,2,3}组成 n 的方法数有 f(n) 种。
先暂时说到这里吧,下面贴一下,这个简单代码(引用的哦):
#include <iostream> using namespace std; // Author: Tanky Woo // www.wutianqi.com const int _max = 10001; // c1是保存各项质量砝码可以组合的数目 // c2是中间量,保存没一次的情况 int c1[_max], c2[_max]; int main() { //int n,i,j,k; int nNum; // int i, j, k; while(cin >> nNum) { for(i=0; i<=nNum; ++i) // ---- ① { c1[i] = 1; c2[i] = 0; } for(i=2; i<=nNum; ++i) // ----- ② { for(j=0; j<=nNum; ++j) // ----- ③ for(k=0; k+j<=nNum; k+=i) // ---- ④ { c2[j+k] += c1[j]; } for(j=0; j<=nNum; ++j) // ---- ⑤ { c1[j] = c2[j]; c2[j] = 0; } } cout << c1[nNum] << endl; } return 0; }
我们来解释下上面标志的各个地方:(***********!!!重点!!!***********)
① 、首先对c1初始化,由第一个表达式(1+x+x^2+..x^n)初始化,把质量从0到n的所有砝码都初始化为1.
② 、 i从2到n遍历,这里i就是指第i个表达式,上面给出的第二种母函数关系式里,每一个括号括起来的就是一个表达式。
③、j 从0到n遍历,这里j就是(前面i個表达式累乘的表达式)里第j个变量,(这里感谢一下seagg朋友给我指出的错误,大家可以看下留言处的讨论)。如(1+x)(1+x^2)(1+x^3),j先指示的是1和x的系数,i=2执行完之后变为
(1+x+x^2+x^3)(1+x^3),这时候j应该指示的是合并后的第一个括号的四个变量的系数。④ 、 k表示的是第j个指数,所以k每次增i(因为第i个表达式的增量是i)。
⑤ 、把c2的值赋给c1,而把c2初始化为0,因为c2每次是从一个表达式中开始的。
来源:http://www.wutianqi.com/?p=596 (母函数详解)
以后再接触,再继续更改。