母函数简介

母函数

母函数又称生成函数,说实话,在实验室待了一年半了,都准备接手实验室了才听说有这么个算法,还是在老板的算法基础课上学的……母函数属于组合数学的知识,在竞赛上主要用于解决这两大类问题:
一、数量有限制的:
有1克、2克、3克、4克的砝码各一个,问能称出哪几种重量,称出某个重量有多少种方案。
二、数量没限制的:
有1元、2元、5元的硬币各无限个,问凑出某个面值有多少种方案。

大体上分母函数就是用于解决这两种问题的,其它的问题都是由这两种问题拓展而来的。母函数的原理在这里就不多说了,这篇博客就是一个小随笔,毕竟老长时间没更博客了,随手写一篇吧。

例题

都是些简单的问题。

Square Coins

#include <iostream>
using namespace std;
#define N 305
int a[N],b[N];
int main()
{
    int n;
    while(cin >> n)
    {
        if(!n) break;
        for(int i=0;i<=n;i++)
        {
            a[i]=1;
            b[i]=0;
        }
        for(int i=2;i<=17;i++)
        {
            for(int j=0;j<=n;j++)
                for(int k=0;j+k<=n;k+=i*i)
                    b[j+k]+=a[j];
            for(int j=0;j<=n;j++)
            {
                a[j]=b[j];
                b[j]=0;
            }
        }
        cout << a[n] << endl;
    }
    return 0;
}

Ignatius and the Princess III

#include <iostream>
using namespace std;
#define N 125
int a[N],b[N];
int main()
{
    int n;
    while(cin >> n)
    {
        for(int i=0;i<=n;i++)
        {
            a[i]=1;
            b[i]=0;
        }
        for(int i=2;i<=n;i++)
        {
            for(int j=0;j<=n;j++)
                for(int k=0;j+k<=n;k+=i)
                    b[j+k]+=a[j];
            for(int j=0;j<=n;j++)
            {
                a[j]=b[j];
                b[j]=0;
            }
        }
        cout << a[n] << endl;
    }
    return 0;
}

Holding Bin-Laden Captive!

#include <iostream>
#include <cstring>
using namespace std;
#define N 8005
int a[N],b[N];
int main()
{
    int num[5],val[5]={0,1,2,5};
    while(cin >> num[1] >> num[2] >> num[3])
    {
        if(!num[1]&&!num[2]&&!num[3]) break;
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        int sum=num[1]*val[1]+num[2]*val[2]+num[3]*val[3];
        for(int i=0;i<=num[1];i++) a[i]=1;
        for(int i=2;i<=3;i++)
        {
            for(int j=0;j<=sum;j++)
                for(int k=0;j+k<=sum&&k<=num[i]*val[i];k+=val[i])
                    b[j+k]+=a[j];
            for(int j=0;j<=sum;j++)
            {
                a[j]=b[j];
                b[j]=0;
            }
        }
        int ans;
        for(int i=0;i<=sum+1;i++)
        {
            if(!a[i])
            {
                ans=i;
                break;
            }
        }
        cout << ans << endl;
    }
    return 0;
}

找零钱

#include <iostream>
using namespace std;
#define N 255
int val[10]={0,1,2,5,10,20,50,100};
int a[N][105],b[N][105],ans[N];
int main()
{
    a[0][0]=1;
    for(int i=1;i<=7;i++)
    {
        for(int j=0;j<=250;j++)
            for(int k=0;j+k<=250;k+=val[i])
                for(int l=0;k/val[i]+l<=100;l++)
                    b[j+k][k/val[i]+l]+=a[j][l];
        for(int j=0;j<=250;j++)
        {
            for(int k=0;k<=100;k++)
            {
                a[j][k]=b[j][k];
                b[j][k]=0;
            }
        }
    }
    for(int i=0;i<=250;i++)
        for(int j=0;j<=100;j++)
            ans[i]+=a[i][j];
    int n;
    while(cin >> n)
    {
        if(!n) break;
        else cout << ans[n] << endl;
    }
    return 0;
}

近期感想

最近一直在刷题,但是刷来刷去发现在打比赛时我们队基本上都还是单兵作战,各想各的,没有什么团队配合。毛老师也说过,想我们这样的弱校更应当靠团队,靠个人去争金夺银难度有点大,但是我们队打组队赛跟打个人赛差不多,基本上依靠的还是个人能力,但是21级的就不一样了,他们现在虽然个人能力还不行,但是他们组起队来实力变了不止一点半点,我感觉如果做的顺的话他们的成绩甚至可能比我们还好……不管怎么说,增强自身的实力是绝对没错的,还得多练多做。另外今天给21级的讲基础dp,把21级的给讲傻了,我讲的方向有点问题,讲的是已知状态转移方程求代码在怎么写……好吧说实话讲的时候确实没注意到,以至于今天晚上又重新讲了一下,讲了两遍才基本上能让21级的理解,今天讲课的失误有些大啊,总感觉挺对不起21级的,呜呜……

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值