题目
现在有 种面值的硬币,其中前 种为普通币,可以取任意枚,后 种为纪念币,每种最多只能取 枚,每种硬币有一个面值,问能用多少种方法拼出 的面值?
输入格式
第一行包含三个整数 ,分别表示普通币种类数,纪念币种类数和目标面值;
第二行 个整数,第 种普通币的面值 。保证 为严格升序;
第三行 个整数,第 种纪念币的面试 。保证 为严格升序。
输出格式
共一行,包含一个整数 ,表示方法总数对 取模后的结果。
注意,不要忘记取模。
数据范围
对于 的数据,保证 。
对于 的数据,保证 。
输入样例:
3 1 5
1 2 3
1
输出样例:
9
样例解释
(x) 代表面值为x的普通币,[x]代表面值为x的纪念币,样例所有方法数如下:
(1)(1)(1)(1)(1)
(1)(1)(1)(2)
(1)(1)(3)
(1)(2)(2)
(2)(3)
(1)(1)(1)(1)[1]
(1)(1)[1](2)
(1)[1](3)
[1](2)(2)
题解
2维dp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| #include <iostream>
using namespace std;
const int N = 100010, MOD = 1e9 + 7;
int f[110][N];
int main() { int n1, n2, m; cin >> n1 >> n2 >> m;
for (int i = 1; i <= n1 + n2; ++ i) f[i][0] = 1;
for (int i = 1; i <= n1; ++ i) { int p; cin >> p; for (int j = 1; j <= m; ++ j) { f[i][j] = f[i - 1][j]; if (j >= p) f[i][j] = (f[i][j] + f[i][j - p]) % MOD; }
}
for (int i = n1 + 1; i <= n1 + n2; ++ i) { int p; cin >> p; for (int j = 1; j <= m; ++ j) { f[i][j] = f[i - 1][j]; if (j >= p) f[i][j] = (f[i][j] + f[i - 1][j - p]) % MOD; } }
cout << f[n1 + n2][m] << endl;
return 0;
}
|
1维优化dp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| #include <iostream>
using namespace std;
const int N = 100010, MOD = 1e9 + 7;
int f[N];
int main() { int n1, n2, m; cin >> n1 >> n2 >> m;
f[0] = 1;
for (int i = 1; i <= n1; ++ i) { int p; cin >> p; for (int j = p; j <= m; ++ j) { f[j] = (f[j] + f[j - p]) % MOD; }
}
for (int i = 1; i <= n2; ++ i) { int p; cin >> p; for (int j = m; j >= p; -- j) { f[j] = (f[j] + f[j - p]) % MOD; } }
cout << f[m] << endl;
return 0;
}
|