已知正整数n,将其分为0到多个25、10、5、1这四个数的和。如n为11可分为一个10和一个1,或者分为两个5和一个1。返回n有多少种分法。保证n小于等于100000,请将答案Mod 1000000007以防止溢出。
测试样例:
6
返回:2
import java.util.*; public class Coins { public int countWays(int n) { // write code here int[] v= {1,5,10,25}; int[] dp=new int[n+1]; dp[0]=1; for(int i=0;i<v.length;i++) { for(int j=1;j<=n;j++) { if(j>=v[i]) { dp[j]=(dp[j]+dp[j-v[i]])%1000000007; } } } return dp[n]; } }
public int countWays11(int n) { // write code here /* * 问题解析 首先如果只用一种硬币的话,那么只有一种解法 接下来,如果我在前一种硬币的基础上又用了一种硬币那么我的解法就变成两种了 好了 * 我们模拟下 首先我的硬币只有面值1 2 那么我要组合成面值为四 有多少种解法呢 1.我们只用面值1的硬币 那么就是 1 1 1 1 * 这里就有1种解了 2.接下来我们要用面值为2的硬币在用了面值1硬币的基础上 那么就得在 1 1 后用 2 此时已经有了2种解法了 * 3.那么此时采用了1个面值为2的硬币啊,按道理说我们是可以用两个面值为2的硬币的,所以我们继续向下走 在 1 2 1 1的基础上 * 我们来到了第三个位置此时我们放入一个面值2的硬币发现此时是用了1个面值1的硬币 和一个面值2的硬币,所以我们总共的总数还是只能有2种 * 1 2 2 1 那么接下来我们来到了4的位置 我们又用了1个 面值2的硬币,那么我们得到 了1 2 2 3 为什么呢 我的位置四就有3种了呢 * 好,让我们来分析分析 第一种那就是全部用面值1的硬币达到了4 第二种是 用面值 1 1 2达到了4 第三种是用了2 2 达到了4 * 由此我们可以用dp[n+1]来存储结果 首先dp[0] = 1; 为什么我的dp[0]要等于1呢,是因为我们第一次使用某一种 * 硬币面值的时候需要在0面值的基础上增1,所以我们的dp[0] = 1就是为我们这样服务的。 那么我们再来解析下dp[]数组的含义 * ,他代表着我们前面使用的所有硬币的数量以及到达n种数 1.【1 1 1 1】 2.【1 2 2 1】 3.【1 2 2 3】 * 1.位置二的1代表我们用了一个面值一的硬币以及我们到达位置2用了两个面值1的硬币 * 2.位置二的2代表了我们在1.的基础上用了面值2的硬币到达了2所以我们此时就有2种方法 下面给出代码 */ //方法一 一维dp int[] coins = { 1, 5, 10, 25 }; int[] dp = new int[n + 1]; dp[0] = 1; for (int i = 0; i < coins.length; i++) { for (int j = coins[i]; j <= n; j++) { dp[j] = (dp[j] + dp[j - coins[i]]) % 1000000007; } } return dp[n]; // 方法二 二维的dp // int [][] dp = new int[coins.length+1][n+1]; // for(int i = 1; i <= coins.length; i++) // { // dp[i][0] = 1; // for(int j = 1; j <= n; j++) // { // if(j < coins[i-1]) // dp[i][j] = dp[i-1][j]; // else dp[i][j] = dp[i-1][j] + dp[i][j-coins[i-1]]; // } // } // return dp[coins.length][n]; }