传送门

把数量用二进制展开,比如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;