复习一下多重背包的二进制分解、0-1背包的逆推、完全背包的顺推思想:
#include <cstdio>
#include <cstring>
#define MAX_M 100000
#define MAX_N 100
int N, M;
int value[MAX_N], amount[MAX_N];
bool can[MAX_M + 1] = {1};
void zeroOnePack(int v)
{
for(int i = M; i >= v; --i) can[i] |= can[i - v];
}
void completePack(int v)
{
for(int i = v; i <= M; ++i) can[i] |= can[i - v];
}
void multiPack(int v, int c)
{
if(v * c >= M) completePack(v);
else{
for(int k = 1; k < c; k <<= 1){
zeroOnePack(k * v);
c -= k;
}
zeroOnePack(c * v);
}
}
int solve()
{
memset(can + 1, false, M);
for(int i = 0; i < N; ++i) multiPack(value[i], amount[i]);
int total = 0;
for(int i = 1; i <= M; ++i){
if(can[i]) ++total;
}
return total;
}
bool input()
{
scanf("%d %d", &N, &M);
if(!N) return false;
for(int i = 0; i < N; ++i) scanf("%d", value + i);
for(int i = 0; i < N; ++i) scanf("%d", amount + i);
return true;
}
int main()
{
while(input()) printf("%d\n", solve());
return 0;
}