母函数简介及简单使用(附HDU 1284 钱币兑换问题 解题报告)

来源:互联网 发布:开票软件登录 编辑:程序博客网 时间:2024/04/30 18:28

       通常来说,母函数的思想就是使用幂级数来表示一个离散数列。例如对于一个数列是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代码供参考:

#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;}