BZOJ2287 消失之物

这题貌似是个权限题qwq,我是用离线题库+本地数据包测的
题目大意:
给你(n)个体积分别为(w[i])的物品和容积(m),问你将每一件物品分别去掉之后,拼出(1)~(m)中每一个体积的方案数的个位数分别是多少,将答案矩阵输出。
输入样例:
3 2
1 1 2
输出样例:
11
11
21
考虑先做一次01背包,得到(f)数组,然后去掉不合法的方案。怎么去掉呢,首先枚举第(i)件物品,令(g[x])表示不用第(i)件物品拼成体积为(x)的方案数,则(g)数组的转移如下:
1.(x<w[i],g[x]=f[x])
2.(x>=w[i],g[x]=f[x]-g[x-w[i]])(可以理解成先限制不选第(i)件物品,最后再选上,方案数就是总方案数减去不合法的方案数)
然后输出(g)数组就行了:

#include <bits/stdc++.h>

using namespace std;

#define N 2000

int n, m, w[N+5], f[N+5], g[N+5];

int main()
{
    //freopen("2287.in", "r", stdin);
    //freopen("2287.out", "w", stdout);
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; ++i) scanf("%d", &w[i]), w[i] = w[i] > m ? m+1 : w[i];
	f[0] = 1;
	for(int i = 1; i <= n; ++i)
		for(int j = m; j >= w[i]; --j) f[j] = (f[j]+f[j-w[i]])%10;
	for(int i = 1; i <= n; ++i)
	{
		for(int j = 0; j < w[i]; ++j) g[j] = f[j];
        for(int j = w[i]; j <= m; ++j) g[j] = ((f[j]-g[j-w[i]])%10+10)%10;
        for(int j = 1; j <= m; ++j) printf("%d", g[j]);
		printf("
");
	}
	return 0;
}
原文地址:https://www.cnblogs.com/dummyummy/p/9978991.html