题目
硬币。给定数量不限的硬币,币值为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
解题思路
首先根据题目的意思,这明显是一个完全背包问题,只不过不同以往,这里要求求取可实现的方法次数,所以背包方式的求解就不再说,今天带来一种数学思维的求解方式,就算你没有学过算法【动态规划】,也应该能做出这道题。
1、根据题意,我们可以得出这样的公式(a枚25分的硬币,b枚10分硬币、c枚5分硬币、d枚1分硬币),根据它给出的硬币种类,所以不管给出多少分的数,都能被这四种硬币所组成(降低了难度)。
25a + 10b + 5c + d =n;2、根据所列式子,我们可以得出如果我们取出 i 枚25分硬币,剩下的数量就留给了10 、5 、1 分的硬币去构成,假设当25分硬币数为 a时,【result1 = n - 25a 】,所以I的取值为【0,n/25】;.
3、b、c、d又可以继续按照第二步骤的方法继续进行分,那么【ressult2 = result1-10b】,因此b的取值为【0,result1/10】;
4、因此c的取值为【0,result2/5】;因为【ressult2 = result1-10b】,则c的取值为【0,result1/5-2b】;
5、当a,b,c定了,d的值也就自然定下来了。因此,所有的表示种类,即为 a、b、c可取值数的组合。
6、b、c、d的不同表示种类有:
7、可能你会很奇怪的问:“为啥要 +1 啊?”,那我问你,它的零不是一种情况吗?对吧。所以相对于b、c、d的取值情况,可获取如下式子:
8、解决了b、c、d的取值,之后便处理a的情况:
代码
class Solution {
public:
int waysToChange(int n) {
const int mod = 1000000007;
int res = 0;
for (int i = 0; i <= n / 25; i ++) {
int result = n - i * 25;
int a = result / 5;
int b = result / 10;
res += (long long)(a + 1)*(b + 1) % mod - (long long)b*(b + 1)% mod;
res %= mod;
}
return res;
}
};