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; }