换零钱问题

现有币值为1分,5分,10分,25分和50分的硬币,各种硬币可以任意取整数枚,也可以不取,问有多少种方法可以使所取的硬币的总币值为1元。

这是个典型的组合数学问题,可以构造生成函数,然后求出某项的系数来得到结果。

生成函数的原理基于加法变乘法,即 xa+b+c+d...=xaxbxcxd...

具体到我们现在这个题,题目是求 1a+5b+10c+25d+50e=100 有多少非负整数解?

对于1分的情况,可构造级数 1+x+x2+x3+...
对于5分的情况,可构造级数 1+x5+x10+x15+...
对于10分的情况,可构造级数 1+x10+x20+x30+...
对于25分的情况,可构造级数 1+x25+x50+x75+...
对于50分的情况,可构造级数 1+x50+x100+x150+...
整体的函数构造为
(1+x+x2+x3+...)(1+x5+x10+x15+...)(1+x10+x20+x30+...)(1+x25+x50+x75+...)(1+x50+x100+x150+...)
其中 x100 前的系数就是这个问题的解

用C语言来解决这个问题

#include <stdio.h>
#include<string.h>

int main() {
    int i,j,k,MAX=100,c1[MAX+5],c2[MAX+5],num[6]={0,1,5,10,25,50};//c1保存x^0,x^1,x^2...的系数,c2为临时数组
    memset(c1,0,sizeof(c1));
    memset(c2,0,sizeof(c2));
    c1[0]=1;//注意为代码简单,我们是从(1,0,0,0,0,0...)*(1+x+x^2+x^3+...)的(1,0,0,0,0,0)开始计算
    for(i=1;i<=5;i++){//共有5个多项式相乘
        for(j=0;j<=MAX;j++){//嵌套的两个for循环计算如(1+x+x^2+...)*(1+x^5+x^10+...)的系数
            for(k=0;j+k*num[i]<=MAX;k++){
                c2[j+k*num[i]] += c1[j];
            }
        }
        memcpy(c1,c2,sizeof(c2));
        memset(c2,0,sizeof(c2));
    }
    printf("%d\n",c1[MAX]);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值