把数量用二进制展开,比如2的3次-1,就可以拆成1个2个和4个,就能够代表所有的容量了,这样的话最多只有20*20一共400个包,做一次01背包即可,非常方便的想法。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod = 1e9+7;
int dp[500][10005],wei[1005],n,q,num;
signed main()
{
int T;
scanf("%lld",&T);
while(T--)
{
num = 0;
scanf("%lld%lld",&n,&q);
for(int i = 1;i <= n; i++)
{
int c,w;
scanf("%lld%lld",&w, &c);
int tmp = 1;
while(c--)
{
wei[++num] = tmp * w;
tmp <<= 1;
}
}
dp[0][0] = 1;
for(int i = 1;i <= num; i++)
{
for(int j = 0;j <= 10000; j++)
{
if(j < wei[i])
dp[i][j] = dp[i-1][j];
else
dp[i][j] = (dp[i-1][j] + dp[i-1][j-wei[i]]) % mod;
}
}
while(q--)
{
int s;
scanf("%lld",&s);
printf("%lld\n",dp[num][s]);
}
}
return 0;