题目描述
A 国一共发行了几种不同面值的硬币,分别是面值 1 元,2 元,5 元,10 元,20 元,50 元, 100 元。假设每种面值的硬币数量是无限的,现在你想用这些硬币凑出总面值为 n 的硬币, 同时你想让选出的硬币中,不同的面值种类尽可能多;在面值种类尽可能多的情况下,你想 让选择的硬币总数目尽可能多,请问应该怎么选择硬币呢?
输入描述:
第一行包含一个数字𝑛,表示要凑出的面值。1 ≤ 𝑛 ≤ 109
输出描述:
输出两个整数,分别表示最多能有多少种类型的硬币以及在类型最多的情况下最多能用上多少枚硬币。
示例1
输入
3
输出
2 2
解释
目标值是3, 需要1, 2两种硬币, 面值分别为1, 2共两个
示例2
输入
10
输出
3 5
解释
需要1, 2, 5三种面值, 硬币选择为 1, 1, 1, 2, 5共5枚。
代码
# 算法思想:
# 要求种类最多且数量最多。
# 种类最多时,我们需要尽量的先每一种硬币取一枚, 看能否满足条件,
# 数量最多时, 当我们每一种硬币娶一枚, 仍有剩余的, 就用面值为1的硬币填补, 就可以保证数目最多
target = int(input())
coins = [0, 1, 2, 5, 10, 20, 50, 100]
_sum = [0] * 10
# _sum 中每一个元素表示: 每一种硬币取一枚, 累加的和是多少, 目的是保证种类最多
# _sum = [0, 1, 3, 8, 18, 38, 88, 188]
# 表示,取面值为1的硬币1个, 面值总和为1
# 取面值为1, 2的硬币各一个, 两种硬币, 面值总和为3
# 面值为1, 2, 5 的硬币各一个, 三种硬币, 面值总和为5
# .......
# 这样, 我们就知道,每一种硬币只取一个时, 面值总和是多少。
for i in range(1, len(coins)):
_sum[i] = _sum[i-1] + coins[i]
# 从后往前查询
# target = 100 为例:
# 首先我们应该先保证种类的数目,_sum数组从后往前查询,即先每种面值都先取一个, 取7种面值, 总和是188, 超过了100, 因此不选100面值的硬币
# 然后我们找_sum数组的倒数第二个位置,取6种面值的硬币各一个, 总和88, 小于100, 所以面值种类可以是6, 就是输出中的下标 i
# 下面确定硬币数目。
# 6种面值各一个共88元, 已有i(这里是6)个硬币。
# 还差(target-_sum[i])元, 这些面值全部用1元硬币填补, 需要 (target-_sum[i])个一元硬币。
# 最终总和是 i + (target-_sum[i]) 个硬币。
i = 7
while i >= 1:
if target >= _sum[i]:
print(i, target-_sum[i]+i)
break
i -= 1