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

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

題目大意:n個船,每個船載重vi,數量2^ci-1,問載重正好是s有幾種情況

題目思路:由於固定了數量,所以很容易想到是多重揹包。問的是方案數,所以設dp[0]為1,剩下來初始化為0,然後上去跑多重揹包板子就過了

以下是程式碼:

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long 
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
const int MOD = 1e9+7;
const int MAXN = 1e4+5;
struct node{
    int v,c;
}a[30];
ll dp[MAXN];
int main(){
    int n,q,s;
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&q);
        rep(i,1,n)scanf("%d%d",&a[i].v,&a[i].c),a[i].c=(1<<a[i].c)-1;
        memset(dp,0,sizeof(dp));
        dp[0]=1;
        rep(i,1,n){
            if(a[i].c*a[i].v>=MAXN){
                rep(j,a[i].v,MAXN){
                    dp[j]=(dp[j]+dp[j-a[i].v])%MOD;
                }
            }
            else{
                int k=1,temp=a[i].c;
                while(k<temp){
                    per(j,MAXN,k*a[i].v){
                        dp[j]=(dp[j]+dp[j-k*a[i].v])%MOD;
                    }
                    temp-=k;
                    k<<=1;
                }
                per(j,MAXN,temp*a[i].v){
                    dp[j]=(dp[j]+dp[j-temp*a[i].v])%MOD;
                }
            }
        }
        rep(i,1,q){
            scanf("%d",&s);
            printf("%lld\n",dp[s]);
        }
    }
    return 0;
}