bzoj1042题解

【题意分析】

  有q个询问,每次询问求一个只有四个物品的背包方案数。

【解题思路】

  先计算出所有面值硬币的无限背包方案数。

  考虑容斥,每个限制表示选取大于di个面值ci的硬币,总方案数=0限制方案数-1限制方案数+2限制方案数-3限制方案数+4限制方案数。

  总复杂度O(max(s)+24)。

【参考代码】

 1 #pragma GCC optimize(2)
 2 #include <cstdio>
 3 #include <cstring>
 4 #define REP(i,low,high) for(register int i=(low);i<=(high);i++)
 5 #define for_range(i,size) for(register int i=0;i<(size);i++)
 6 using namespace std;
 7 int T,c[100010],d[100010]; unsigned long long f[100010];
 8 unsigned long long query(const short &now,const int &tar,const short &sig)
 9 {
10     return tar<0?0ull:(now>3?sig*f[tar]:query(now+1,tar,sig)+query(now+1,tar-c[now]*(d[now]+1),-sig));
11 }
12 int main()
13 {
14     memset(f,0,sizeof f),f[0]=1ull; for_range(i,4) {scanf("%d",c+i); REP(j,c[i],100000) f[j]+=f[j-c[i]];}
15     for(scanf("%d",&T);T--;) {int s; for_range(i,4) scanf("%d",d+i); scanf("%d",&s),printf("%llu
",query(0,s,1));}
16     return 0;
17 }
View Code
原文地址:https://www.cnblogs.com/spactim/p/6511737.html