有找零钱说起……

丢人了,Projece Euler上的第31问做了两天都还没搞定。不难啊,可脑子就是想不清楚,唉,老矣。

题目是这样的:现有面值为1分、2分、5分、10分、20分、50分、1磅(100分)、2磅(200分)的硬币,问2磅钱可以有多少种兑换方案?

这是经典的找零钱问题。

我是这么考虑的,既然要求所有的兑换方案,那我只要把问题规约到这些面额组成的集合的子集上就行了。当我用某一子集来兑换时,该子集上的每种硬币至少含1枚。 我们来看个简化的实例:现有1分、2分和5分三种硬币,兑换10分钱有多少种方法?

当我们去集合{1, 2, 5}时,因为5+2+1已经是8了,故只要再加上2的方案,即,5+2+2+1, 5+2+1+1+1;

当我们去集合{2, 5}时,因为5+2=7,而3不可能用{2, 5} 的整数线性组合来得到,故在这种情况下不存在兑换方案;

当我们去集合{1, 5}时,方案为:5+1+1+1+1+1;

当我们去集合{1, 2}时,方案为:2+2+2+2+1+1, 2+2+2+1+1+1+1, 2+2+1+1+1+1+1+1, 2+1+1+1+1+1+1+1+1;

当我们去集合{5}时,方案为:5+5;

当我们去集合{2}时,方案为:2+2+2+2+2;

当我们去集合{1}时,方案为:1+1+1+1+1+1+1+1+1+1;

共10种方案。

  • 递归解法

但其实不用这么麻烦,设可选的硬币面值分别为{S1, S2, ...... , Sm},用这些面额的硬币来兑换n分钱有count(n, {S1, S2, ...... , Sm})种方法。有两种不同的兑换方式:

兑换的硬币面额中没有Sm,即count(n, {S1, S2, ...... , Sm});

兑换的零钱中至少有一枚Sm分的硬币,即count(n-Sm{S1, S2, ...... , Sm})。

 

可我有个疑问,对于第二种情况,count(n-Sm{S1, S2, ...... , Sm})真的能代表包含Sm分硬币的所有方案吗?我们需要论证,在只使用{S1, S2, ...... , Sm}硬币时,含Sm分硬币的n分兑换方案数不比n-Sm分的少。用反证法,如果n-Sm分的方案数比n分的多,那么在多的那些方案中添上一枚Sm分硬币即可得到新的兑换方案,矛盾。同样,如果n-Sm分的方案数比n分的少,那么在n分兑换方案中多的那些方案中剔除一枚Sm分硬币(这些方案至少有一枚Sm分硬币)即可得到新n-Sm分兑换方案,也矛盾。

这里还隐含了:count(Sm-Sm{S1, S2, ...... , Sm}) = 1

还是那个例子:

 1: 1

 2: 2, 1+1

 3: 2+1, 1+1+1

 4: 2+2, 2+1+1, 1+1+1+1

 5: 5, 2+2+1, 2+1+1+1, 1+1+1+1+1

 6: 5+1, 2+2+2, 2+2+1+1, 2+1+1+1+1, 1+1+1+1+1+1

 7: 5+2, 5+1+1, 2+2+2+1, 2+2+1+1+1, 2+1+1+1+1+1, 1+1+1+1+1+1+1

 8: 5+2+1, 5+1+1+1, 2+2+2+2, 2+2+2+1+1, 2+2+1+1+1+1, 2+1+1+1+1+1+1, 1+1+1+1+1+1+1+1

 9: 5+2+2, 5+2+1+1, 5+1+1+1+1, 2+2+2+2+1, 2+2+2+1+1+1, 2+2+1+1+1+1+1, 2+1+1+1+1+1+1+1, 1+1+1+1+1+1+1+1+1

10: 5+5, 5+2+2+1, 5+2+1+1+1, 5+1+1+1+1+1, 2+2+2+2+2, 2+2+2+2+1+1, 2+2+2+1+1+1+1, 2+2+1+1+1+1+1+1, 2+1+1+1+1+1+1+1+1, 1+1+1+1+1+1+1+1+1+1

以6为例,兑换方案分为两组:

一组是6中不含{5}的兑换方案:2+2+2, 2+2+1+1, 2+1+1+1+1, 1+1+1+1+1+1

一组是6-5的兑换方案加上5:1+5

Problem 31

  • 生成函数解法

另一种思路来自生成函数:

Problem 31

要想知道为什么系数就是兑换方案的种数,请参阅:組合數學中的生成函數什么是生成函数?

Mathematica代码:

Problem 31

最后给几个作弊招数:

 

 

 

P.S. 优快云的编辑器实在太烂了-_-!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值