「这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战」
描述
硬币。给定数量不限的硬币,币值为25分、10分、5分和1分,编写代码计算n分有几种表示法。(结果可能会很大,你需要将结果模上1000000007)
- 示例 1:
输入: n = 5
输出:2
解释: 有两种方式可以凑成总金额:
5=5
5=1+1+1+1+1
- 示例 2:
输入: n = 10
输出:4
解释: 有四种方式可以凑成总金额:
10=10
10=5+5
10=5+1+1+1+1+1
10=1+1+1+1+1+1+1+1+1+1
- 提示:
- 0 <= n (总金额) <= 1000000
解析
我们先遍历硬币,保证在考虑一枚硬币的情况时,没有较大的硬币影响,这样,我们最终每种组合情况,都是以硬币的面额大小非递减组合。保证了同样的情况,调换顺序后重复计算的情况。
当25的数量固定后,应该还有after25 = n - 25 * i的金钱来考虑三种硬币组合,为了方便,用t来表示吧 10的硬币可以有 t/10 张 采用0张时, 即i张25,0张10,方法有(t - 0 * 10) / 5 + 1种; 1张时, (t - 1 * 10) / 5 + 1; ...... t / 10 张时, (t - t / 10 * 10) / 5 + 1; (然后是等差数列求和,公差为2,注意带除的项不要轻易合并) 于是, i张25,剩下t = n - 25 * i余额时,三种金币组合方式有这么多种: t / 10 + 1 + (t / 5 + t / 5 - t / 10 - t / 10) * (t / 10 + 1) / 2
代码再简化一下,只剩一个for了 然后,res += 右边在计算时会可能大于INT_MAX, 所以t先用long接,之后再转回来。
class Solution {
private static final int[] coins = {25, 10, 5, 1};
private static final int mod = 1000000007;
public int waysToChange(int n) {
int[] temp = new int[n + 1];
temp[0] = 1;
for(int coin : coins) {
for(int i = coin; i <= n; i++) {
temp[i] = (temp[i] + temp[i - coin]) % mod;
}
}
return temp[n];
}
}
运行结果:
执行结果:通过
执行用时:25 ms, 在所有 Java 提交中击败了85.88%的用户
内存消耗:42.2 MB, 在所有 Java 提交中击败了61.69%的用户