P2834 题解
题意
本题题目描述简短,不多赘述。
思路
由于是组合计数问题,需要考虑到纸币种类这个阶段以及每次加入一种新纸币产生的贡献。
所以使用状态
于是有以下两种情况:
-
用了若干张
a_i ,此时前继状态为f_{i,j-a_i} ,由此转移即可。 -
没有用一张
a_i ,直接f_{i-1,j} 转移即可。
注意:需要初始化边界条件
贴出代码为:
for(int i = 1; i<=n; i++) {
for(int j = 0; j <= w; j++) {
if(j < a[i]) {
f[i][j] = f[i-1][j];
}
else {
f[i][j] = f[i][j-a[i]] + f[i-1][j];
f[i][j] %= mod;
}
}
}
时间复杂度为
但是空间还可以再做优化,观察到
完整代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e3 + 5;
const int W = 1e4 + 5;
const int inf = 2e9;
const int mod = 1e9 + 7;
int n,w;
int a[N];
int f[W];
int main() {
cin>>n>>w;
for(int i = 1; i<=n; i++) {
cin>>a[i];
}
f[0] = 1; //边界
for(int i = 1; i<=n;i++) {
for(int j = a[i]; j<=w; j++) {
f[j] += f[j - a[i]] % mod;
f[j] %= mod;
}
}
cout<<f[w]<<endl;
return 0;
}