母函数 经典题目汇总

HDU 1398 Square Coins(普通母函数 || 完全背包)

题意:
可选钱 种类17种,值分别为    i*i(i>=1&&i<=17)
求组和之和=钱数K的方案数
 
 
分析:
 
方法一:
///DP   完全背包问题(求装入背包)
///f[i]表示
///打表
#include<stdio.h>
int main()
{
    int a[20]={0,1,4,9,16,25,36,49,64,81,100,121,144,169,196,225,256,289},f[305]={0};
    int i,n,j;
    f[0]=1;
    for(i=1;i<=17;i++)///第几种钱
        for(j=a[i];j<=300;j++)///
            f[j]+=f[j-a[i]];
    while(scanf("%d",&n)!=EOF){
        if(n==0)
            break;
        printf("%d\n",f[n]);
    }
    return 0;
}

方法二:

母函数

母函数应用于——————形式上说,普通型生成函数用于解决多重集的组合问题,而指数型母函数用于解决多重集的排列问题.。现在我们先讨论普通生成函数;

这里组合问题,用普通母函数

#include "cstdio"
#define N 305
int c1[N];///记录各次幂系数
int c2[N];///记录中间计算结果
void solve()
{
    for(int i=0;i<=300;i++)///初始化(第一个表达式)
    {
        c1[i]=1;
        c2[i]=0;
    }
    for(int i=2;i<=17;i++)///那个表达式
    {
        for(int j=0;j<=300;j++)
        {
            for(int k=0;k+j<=300;k+=i*i)///此表达式中各项的次幂
            {                           ///(把组合问题的加法法则和幂级数的乘幂对应起来)
                c2[j+k]+=c1[j];
            }
        }
        for(int j=0;j<=300;j++)
        {
            c1[j]=c2[j];
            c2[j]=0;
        }
    }
}
int main()
{
    int n;
    solve();
    while(~scanf("%d",&n),n)
    {
        printf("%d\n",c1[n]);
    }
    return 0;
}

 HDU1028 

Ignatius and the Princess III

题意:

输入一数N,求1-N N种数,任意组合(数不一定都出现和个数任意)之和=N的方案个数

分析:

组合问题

普通母函数

#include "cstdio"
#define N 305
int c1[N];
int c2[N];
void solve()
{
    for(int i=0;i<=120;i++)
    {
        c1[i]=1;
        c2[i]=0;
    }
    for(int i=2;i<=120;i++)
    {
        for(int j=0;j<=120;j++)
        {
            for(int k=0;k+j<=120;k+=i)
            {
                c2[k+j]+=c1[j];
            }
        }
        for(int j=0;j<=120;j++)
        {
            c1[j]=c2[j];
            c2[j]=0;
        }
    }
}
int main()
{
    int n;
    solve();
    while(scanf("%d",&n)!=EOF)
    {
        printf("%d\n",c1[n]);
    }
}

 

HDU1085
题意:1 2 5三种数,你赋予他们数量,求他们组成和不能组成的最小数

个数有限

#include "cstdio"
#include "iostream"
#include "cstring"
using namespace std;
#define N 10000
int c1[N];
int c2[N];
int num[4];
int Max;
void solve()
{
    num[1]*=2;num[2]*=5;
    Max=num[0]+num[1]+num[2];
    memset(c1,0,sizeof(c1));
    memset(c2,0,sizeof(c2));
    for(int i=0;i<=num[0];i++)
    {
        c1[i]=1;
    }
    for(int j=0;j<=num[0];j++)
        for(int k=0;k+j<=num[0]+num[1];k+=2)
        c2[k+j]+=c1[j];
    for(int i=0;i<=num[0]+num[1];i++)
    {
        c1[i]=c2[i];c2[i]=0;
    }
    for(int j=0;j<=num[0]+num[1];j++)
        for(int k=0;k+j<=num[0]+num[1]+num[2];k+=5)
        c2[k+j]+=c1[j];
    for(int i=0;i<=num[0]+num[1]+num[2];i++)
    {
        c1[i]=c2[i];c2[i]=0;
    }
}
int main()
{
    while(scanf("%d%d%d",&num[0],&num[1],&num[2])!=EOF&&(num[0]||num[1]||num[2]))
    {
        solve();
        int i;
        for(i=0;i<=Max;i++)
        {
            if(c1[i]==0)
            {
                printf("%d\n",i);
                break;
            }
        }
        if(i==Max+1)
            printf("%d\n",i);
    }
}

 

posted @ 2017-04-14 15:20  kimsimple  阅读(1077)  评论(0编辑  收藏  举报