题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1101
题意:中文题诶~
思路:dp
我们用dp[i][j]存储前i中币值总价值为j的方法数,那么动态转移方程式为:
if(j>=gg[i]) //放的下第i中币值
dp[i][j]=dp[i-1][j]+dp[i][j-gg[i]]
else //放不下第i中币值
dp[i][j]=dp[i-1][j]
代码:
1 #include <iostream>
2 #define ll long long
3 #define MAXN 100010
4 using namespace std;
5
6 const int mod=1e9+7;
7 ll gg[]={0, 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000};
8 ll dp[15][MAXN]; //***dp[i][j]存储前i中币值总价值为j的方法数
9
10 int main(void){
11 int n;
12 cin >> n;
13 dp[0][0]=1;
14 for(int i=1; i<=13; i++){
15 for(int j=0; j<=n; j++){
16 if(j>=gg[i]){ //***放的下
17 dp[i][j]=(dp[i-1][j]+dp[i][j-gg[i]])%mod;
18 }else{ //***放不下
19 dp[i][j]=dp[i-1][j];
20 }
21 }
22 }
23 cout << dp[13][n] << endl;
24 return 0;
25 }
因为dp[i][]的情况都是由dp[i-1]得到的,所以我们可以直接用一维数组就好了~
代码:
1 #include <iostream>
2 #define ll long long
3 #define MAXN 100010
4 using namespace std;
5
6 const int mod=1e9+7;
7 ll gg[]={1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000};
8 ll dp[MAXN];
9
10 int main(void){
11 int n;
12 cin >> n;
13 dp[0]=1;
14 for(int i=0; i<13; i++){ //***选用前i+1种币值
15 for(int j=gg[i]; j<=n; j++){ //***总价值为j的方法数
16 dp[j]=(dp[j]+dp[j-gg[i]])%mod;
17 }
18 }
19 cout << dp[n] << endl;
20 return 0;
21 }