1. 程式人生 > >ACM-ICPC 2018 焦作賽區網路預賽 Transport Ship (多重揹包)

ACM-ICPC 2018 焦作賽區網路預賽 Transport Ship (多重揹包)

There are NN different kinds of transport ships on the port. The i^{th}ith kind of ship can carry the weight of V[i]V[i] and the number of the i^{th}ith kind of ship is 2^{C[i]} - 12C[i]−1. How many different schemes there are if you want to use these ships to transport cargo with a total weight of SS?

It is required that each ship must be full-filled. Two schemes are considered to be the same if they use the same kinds of ships and the same number for each kind.

Input

The first line contains an integer T(1 \le T \le 20)T(1≤T≤20), which is the number of test cases.

For each test case:

The first line contains two integers: N(1 \le N \le 20), Q(1 \le Q \le 10000)N(1≤N≤20),Q(1≤Q≤10000), representing the number of kinds of ships and the number of queries.

For the next NN lines, each line contains two integers: V[i](1 \le V[i] \le 20), C[i](1 \le C[i] \le 20)V[i](1≤V[i]≤20),C[i](1≤C[i]≤20), representing the weight the i^{th}ith kind of ship can carry, and the number of the i^{th}ith kind of ship is 2^{C[i]} - 12C[i]−1.

For the next QQ lines, each line contains a single integer: S(1 \le S \le 10000)S(1≤S≤10000), representing the queried weight.

Output

For each query, output one line containing a single integer which represents the number of schemes for arranging ships. Since the answer may be very large, output the answer modulo 10000000071000000007.

樣例輸入複製

1
1 2
2 1
1
2

樣例輸出複製

0
1

題目來源

解題思路:每個船的個數有2的i次方-1個,剛好的分解成i個每個容量為v[i]*2的多少次冪,並且這些數可以組成該數這內所有的數

這也正是能用2進位制優化的原因。其餘的和求01揹包能裝滿的方案有多少種一樣。

#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define sca(x) scanf("%d",&x)
#define per(i,j,k) for(int i=j;i>=k;i--)
#define inf 0x3f3f3f3f
#define mod 1000000007
#define LL long long
LL  dp[10005];
LL  a[36],b[30];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n,q;
        sca(n),sca(q);
        rep(i,1,n)
        {
            scanf("%lld%lld",a+i,b+i);
        }
        memset(dp,0,sizeof(dp));
        dp[0]=1;
        rep(i,1,n)
        {
           rep(k,0,b[i]-1)
           {
               per(j,10000,a[i]*(1LL<<k))
               {
                    if((1LL<<k)*a[i]<=j)
                    {
                        dp[j]=(dp[j]+dp[j-(1LL<<k)*a[i]])%mod;
                    }
               }
           }
        }
        rep(i,1,q)
        {
            int qq;
            sca(qq);
            printf("%lld\n",dp[qq]);
        }
    }
}
/*
1
4 2
1 1
1 1
2 1
2 1
4
3
*/