转自:http://blog.csdn.net/geniusluzh/article/details/6788182
通常来说,母函数的思想就是使用幂级数来表示一个离散数列。例如对于一个数列是a={a0,a1,a2,-------ak},那么我们可以母函数的定义就是G(x)=a0+a1*x+a2*x^2+a3*x^3------an*x^n,这里的G(x)就是数列a的母函数。
母函数可以用来解决整数拆分问题,下面举一个例子来说明。
例如我们有重量为1克、2克、3克、4克的砝码各一个,那么问你这些砝码可以称出几中重量?每一种重量有多少种方案数?
对于这个问题我们可以这样定义母函数G(x)=(1+x)*(1+x^2)*(1+x^3)*(1+x^4),那么这个时候我们把G(x)展开之后得到一个多项式,这个时候的指数就是可以称出的重量,对应的该指数的系数就是该重量对应的称出的方案数,自己展开看看就知道了。
下面我们说说HDU 1284 的“钱币兑换问题”吧,题目的意思就是说给你三种面值的币分别是1分、2分、3分,那么问你一个钱数n有几种方案可以拼凑得到这个钱数n?
这道题还是比较好看的,我们根据母函数的定义,以及多项式的每一项和系数所表示的含义,我们可以定义母函数G(x)=(1+x+x^2+x^3--------)*(1+x^2+x^4+x^6+x^8--------)*(1+x^3+x^6+x^9--------------),那么我们使用母函数的额展开式对应的指数就是能表示的钱币数,系数就是表示该钱币数的方案数。
所以问题就是求出对应的n的系数就可以了,这个比较简单,就是模拟手工多项式的展开,下面附上我的AC代码供参考:
- <span style="font-size:18px;">#include <iostream>
- #include <cstring>
- #include <cstdlib>
- #include <cstdio>
- using namespace std;
- const int Max=32769;
- int ans[Max];
- int tans[Max];
- int main()
- {
- int i,j,n;
- for(int i=0;i<Max;i++)
- ans[i]=1;
- memset(tans,0,sizeof(tans));
- for(int k=2;k<=3;k++)
- {
- for(i=0;i<Max;i++)
- {
- for(j=0;i+j<Max;j+=k)
- {
- tans[i+j]+=ans[i];
- }
- }
- for(i=0;i<Max;i++)
- {
- ans[i]=tans[i];
- tans[i]=0;
- }
- }
- while(scanf("%d",&n)!=EOF)
- {
- printf("%d\n",ans[n]);
- }
- return 0;
- }
- </span>