ACM-ICPC 2018 焦作赛区网络预赛 K Transport Ship (多重背包)

https://nanti.jisuanke.com/t/31720

题意

t组样例,n种船只,q个询问,接下来n行给你每种船只的信息:v[i]表示这个船只的载重,c[i]表示这种船只有2^(c[i]1)只。

对于每个询问,求用这些船装s的货物的方案数有多少,用到的船必须装满。 

分析

一眼就是背包类的题,多重背包求方案数,将数量为m的物体分为log2(m)种物体,然后做01背包。在这里只需改改多重背包模板的转移式子就好。

背包九讲小总结:https://www.cnblogs.com/fht-litost/p/9204147.html

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e4+10;
const int mod = 1e9 + 7;

ll F[maxn];
int V=10000;
void ZeroOnePack(int C){
    for(int v = V; v>=C ; v--)
        F[v] = (F[v]+F[v-C])%mod;
}
void CompletePack(int C){
    for(int v = C; v<=V ; v++)
        F[v] = (F[v]+F[v-C])%mod;
}
void MultiplePack(int C,int M){
    if( C*M >= V ){
        CompletePack(C);
        return;
    }
    int k = 1;
    while( k < M ){
        ZeroOnePack(k*C);
        M = M - k;
        k <<= 1;
    }
    ZeroOnePack(M*C);
}

int main(){
       int t;
    scanf("%d",&t);
    while(t--){
        int n,q,s,v,c;
        scanf("%d%d",&n,&q);
        memset(F,0,sizeof(F));
        F[0]=1;
        for(int i=1;i<=n;i++){
            scanf("%d%d",&v,&c);
            c=(1<<c)-1;
            MultiplePack(v,c);
        }
        while(q--){
            scanf("%d",&s);
            printf("%lld\n",F[s]);
        }
    }
    return 0;
}

 

posted @ 2018-09-17 16:57  litos  阅读(215)  评论(0编辑  收藏  举报