Bzoj2287

如果联想到 https://www.luogu.com.cn/problem/P4095 ,只有 $O(n^3)$ 的复杂度,即使加了卷积也只有 $O(n^2\log n)$ 。

考虑 01 背包,$f[i][j]=f[i-1][j]+f[i-1][j-v[i]]$

令 $g_j$ 表示除了 $i$ 以外的装满容积为 $j$ 的方案。

01 背包无所谓物品的顺序,所以 $g[j]=f[n][j]-g[j-v[i]]$

输出 $g[j]\bmod 10$ 即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include<bits/stdc++.h>
#define maxn 2005
#define int long long
#define put() putchar('\n')
using namespace std;
inline void read(int &x){
int f=1;x=0;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
x*=f;
}
const int mod=10;
int f[maxn],g[maxn];
int v[maxn],n,m;
signed main(void){
freopen("1.in","r",stdin);
int i,j;
read(n);read(m);
for (i=1;i<=n;i++) read(v[i]);
f[0]=1;
for (i=1;i<=n;i++) {
for (j=m;j>=v[i];j--) f[j]+=f[j-v[i]],f[j]%=mod;
// for (j=0;j<=m;j++) printf("%d ",f[j]);put();
}
for (i=1;i<=n;i++) {
for (j=0;j<=m;j++) g[j]=f[j];
for (j=v[i];j<=m;j++) g[j]=(g[j]-g[j-v[i]]+mod)%mod;
for (j=1;j<=m;j++) printf("%lld",g[j]);put();
}
return 0;
}