1. 程式人生 > >ACM-ICPC 2018 焦作賽區網路預賽 Transport Ship—— 二進位制優化的01揹包

ACM-ICPC 2018 焦作賽區網路預賽 Transport Ship—— 二進位制優化的01揹包

There are NN different kinds of transport ships on the port. The i^{th}i th kind of ship can carry the weight of V[i]V[i] and the number of the i^{th}i th kind of ship is 2^{C[i]} - 12 C[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)Vi,Ci, representing the weight the i^{th}i th kind of ship can carry, and the number of the i^{th}i th kind of ship is 2^{C[i]} - 12 C[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 題目連結:https://nanti.jisuanke.com/t/31720 題意: t組樣例,n種船隻,q個詢問,接下來n行給你每種船隻的資訊:wei[i]表示這個船隻的載重,c[i]表示這種船隻有2c[i]1只 那麼我們就可以用二進位制優化來做,既然是2c1,那麼就是20+21+22+...+2c1,存在wei裡面 接下來就是揹包了,dp[i][j]表示拿到第i個wei的時候到達j有多照中方法

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=(int)1e9+7;
const int maxn=1005;
int dp[500][10005];
int wei[1005],n,q,s;
int ar;
int main(){
    int t;
    cin>>t;
    while(t--){
        ar=0;
        scanf("%d%d",&n,&q);
        for(int i=1;i<=n;i++){
            int v,c;
            scanf("%d%d",&v,&c);
            int ba=1;
            while(c--){
                wei[++ar]=ba*v;
                ba*=2;
            }
        }
        dp[0][0]=1;
        for(int i=1;i<=ar;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("%d",&S);
            printf("%d\n",dp[ar][S]);

        }
    }

    return 0;
}