题目大意:
先做一遍01背包,得到 $f$ 数组,其中 $f[i]$ 表示装满容量为 $i$ 的背包的方案数。
然后枚举当前物品,减掉它的贡献,$g[j] -= g[j-w[i]]$ 相当于减去用 $w[i]$ 装满容量为 $j$ 的背包的方案数,而 $j$ 要顺序枚举的原因是,我们要保证 $g[j-w[i]]$ 的方案数里已经不存在 $w[i]$ 了。
#include <cstdio>
#include <cstring>
int f[2005], g[2005], w[2005], n, m;
int main() {
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; ++i) scanf("%d", &w[i]);
f[0] = 1;
for (int i = 1; i <= n; ++i)
for (int j = m; j >= w[i]; --j) (f[j] += f[j-w[i]]) %= 10;
for (int i = 1; i <= n; ++i) {
memcpy(g, f, sizeof f);
for (int j = w[i]; j <= m; ++j) g[j] = (g[j] - g[j-w[i]] + 10) % 10;
for (int j = 1; j <= m; ++j) printf("%d", g[j]);
puts("");
}
return 0;
}
时间复杂度 $O(nm)$