母函数

普通型: 1.求每种数字个数无限个,求组成N的组合数,例如2为两个1+1和2。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include<utility>
#include<sstream>
#include<cmath>
#include <algorithm>
using namespace std;
int a[100001],b[100001];
// a是保存各项质量砝码可以组合的数目
// b是中间量,保存每一次的情况
int main()
{
    int n;
    while(~scanf("%d",&n))//此时的n是第一个括号的所有项个数
    {
        memset(a,0,sizeof(a));
        //我们用下标来表示砝码重量,用a[i]值来表示i的数量
        for(int i=0; i<=n; i++)
        {
            a[i]=1;
            b[i]=0;
        }
        for(int i=2; i<=n; i++) //n 括号个数
        {
            for(int j=0; j<=n; j++) //j是第一个括号里的每一项x^j的指数j
            {
                for(int  k=0; k+j<=n; k+=i) //k第二个括号的每一项x^k的指数
                {
                    b[j+k]+=a[j];//目前的第一括号与第二括号两两相乘
                }//由于第二括号的系数全为1,相乘后的系数就是a[j],累加即可
            }

            for(int j=0; j<=n; j++)
            {// 把b中的值给a,并把b清0
                a[j]=b[j];
                b[j]=0;
            }
        }
        printf("%d\n",a[n]);//输出能组成nNum大小的方案数
    }
    return 0;
}

2.三种硬币价值分别为1 2 5,数目输入。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include<utility>
#include<sstream>
#include<cmath>
#include <algorithm>
using namespace std;
int b1[100001],b[100001];
int a1[100001];
// b1是保存各项质量砝码可以组合的数目
// b是中间量,保存每一次的情况
 
//b1的下标表示的是每一项x^i的系数,函数中的每一项系数
int main()
{

    int aa,bb,c;;
    while(~scanf("%d%d%d",&aa,&bb,&c))
    {
        if(aa==0&&bb==0&&c==0)
            return 0;
        memset(a1,0,sizeof(a1));
        memset(b,0,sizeof(b));
        memset(b1,0,sizeof(b1));
        //我们用下标来表示砝码重量,用a1[i]值来表示i的数量
        //价值1的有aa个,2的有bb个,5的有c个。
        a1[1]=aa;
        a1[2]=bb;
        a1[5]=c;
        int maxx=1*aa+bb*2+c*5;
        //maxx记下所有砝码可以组成的最大重量,即总和最大
        for(int i=0;i<=aa;i++)
        {
            b1[i]=1;
            b[i]=0;
        }
        int temp=aa;//始终代表第一括号的最大的指数
        for(int i=2;i<=5;i++)
        {
            if(a1[i]==0)//i重量砝码有0个,所以没必要计算
                continue;
            for(int j=0;j<=temp;j++)
            {//j是第一个括号里的每一项x^j的指数
                for(int k=0;k<=a1[i]*i;k+=i)
                {//k第二个括号的每一项x^k的指数
                    b[j+k]+=b1[j];//目前的第一括号与第二括号两两相乘
                }
            }
            /*上面的k<=a1[i]*i 表示第二括号的结束条件,
                      a1[i]*i是目前的第二括号最大指数*/
            //temp总是记下第一括号的最大的x^j的指数j,便于下一次循环作为结束条件
            temp+=a1[i]*i;
            for(int j=0;j<=maxx;j++)
            {
                b1[j]=b[j];
                b[j]=0;
            }
        }
        //计算完成后就得到了每一种重量的方案数,存在b1中
        for(int i=1;i<=maxx+1;i++)
        {
            if(b1[i]==0)
            {
                printf("%d\n",i);
                break;
            }
        }
    }
    return 0;
}

指数型:模板题  http://acm.hdu.edu.cn/showproblem.php?pid=1521

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <map>
using namespace std;
int a[1001],b[1001];double c[1001],d[1001];
//因为用到了除法,所以用double型来存储。
void ddd()
{
    b[0]=1;
    b[1]=1;
    for(int i=2;i<=31;i++)//记录各个位置的阶乘数
    {
        b[i]=b[i-1]*i;
    }
}
int main()
{
    int n,m;
    ddd();
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        memset(c,0,sizeof(c));
        memset(d,0,sizeof(d));
        for(int i=0;i<=a[1];i++)
        {
            c[i]=1.0/b[i];
        }
        for(int i=2;i<=n;i++)
        {
            for(int j=0;j<=m;j++)
            {
                for(int k=0;k+j<=m&&k<=a[i];k++)
                {
                    d[j+k]+=c[j]/b[k];//这里注意
                }
            }
            for(int j=0;j<=m;j++)
            {
                c[j]=d[j];
                d[j]=0;
            }
        }
        printf("%.lf\n",c[m]*b[m]);//还原
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值