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("\n");
	}
	return 0;
}
posted @ 2018-11-18 21:00  dummyummy  阅读(168)  评论(0编辑  收藏  举报