O(n*m)的背包可以求出用所有物品达到i容量的方案数,
我们可以考虑从其中减掉每种物品的方案得到答案。
由原来的方程f[i]+=f[j](j=i-v[i]) 此时的f[j]未用i物品更新过。
我们从前向后减去每个f[i]对应的f[j],在枚举到i时对应的j已经不包含第i个物品,
直接减掉就可以了。
代码:
#include<cstdio>
#define maxn 2010
using namespace std;
int n,m,f[maxn],g[maxn],w[maxn];
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]];
if(f[j]>=10) f[j]-=10;
}
}
for(int i=1;i<=n;i++){
for(int j=0;j<=m;j++) g[j]=f[j];
for(int j=w[i];j<=m;j++){
g[j]-=g[j-w[i]];
g[j]=(g[j]%10+10)%10;
}
for(int j=1;j<=m;j++) printf("%d",g[j]);
puts("");
}
return 0;
}