【题目描述】
给定数组arr,设数组长度为n,arr中所有的值都为正整数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个整数aim,代表要找的钱数,求换钱的方法数有多少种。由于方法的种数比较大,所以要求输出对10^9+7进行取模后的答案。
【输入描述】
输入包括两行,第一行两个整数n(0<=n<=1000)代表数组长度和aim(0<=aim<=20000),第二行n个不重复的正整数,代表数组arr(其任何一个元素取值介于1到1000000000之间 )。
【输出描述】
输出一个整数,表示换钱的方法数对10^9+7取模后的答案。
【示例1】
输入
4 15
5 10 25 1
输出
6
说明
53=15
101+51=15
101+15=15
110+51=15
52+15=15
115=15
【示例2】
输入
5 1000
2 3 5 7 10
输出
20932712
【备注】
时间复杂度O(N*aim),空间复杂度O(aim)。
【代码实现 - CPP版】
#include<iostream>
#include<vector>
using namespace std;
int static mod = 1e9 + 7;
int count_methods1(const vector<int>& coins, int aim) {
int size = coins.size();
vector<vector<int>> dp(size, vector<int>(aim+1, 0));
// for the first column
for (int i=0; i<size; i++) {
dp[i][0] = 1;
}
// for the first row
for (int j=1; j*coins[0]<=aim; j++) {
dp[0][j*coins[0]] = 1;
}
// other scenarios
for (int i=1; i<size; i++) {
for (int j=1; j<=aim; j++) {
dp[i][j] = dp[i-1][j]%mod;
dp[i][j] = (dp[i][j] + ((j-coins[i]) >=0 ? dp[i][j-coins[i]] : 0))%mod;
}
}
return dp[size-1][aim];
}
int count_methods2(const vector<int>& coins, int aim) {
int size = coins.size();
vector<int> dp(aim+1, 0);
for (int j=0; j*coins[0]<=aim; j++) {
dp[j*coins[0]] = 1;
}
for (int i=1; i<size; i++) {
for (int j=1; j<=aim; j++) {
dp[j] = (dp[j] + ((j-coins[i])>=0 ? dp[j-coins[i]] : 0))%mod;
}
}
return dp[aim];
}
int main() {
int n, aim;
cin >> n >>aim;
vector<int> vec(n, 0);
for (int i=0; i<n; i++) {
cin >> vec[i];
}
cout << count_methods2(vec, aim);
return 0;
}