【背包+容斥】BZOJ1042(HAOI2008)[硬币购物]题解
2017-10-31 10:05
190 查看
题目概述
有 4 种硬币。面值分别为 c1 , c2 , c3 , c4 。某人去商店买东西,去了 tot 次。每次带 di 枚 ci 硬币,买 si 的价值的东西。请问每次有多少种付款方法。解题报告
直接背包会TLE,但由于只有 4 种硬币,所以……所以好难啊!根据容斥,答案为:价值恰好为 s 但硬币数不受限制的方案 − 第一枚硬币超过限制其他硬币不受限制的方案 − 第二枚硬币超过限制其他硬币不受限制的方案 ⋯ + 第一枚第二枚硬币超过限制其他硬币不受限制的方案 ⋯
然后容斥的模型就出来了,但是要如何求出每种情况的方案?首先先用背包求出价值恰好为 i 但硬币数不受限制的方案 f[i] ,则如果第一枚硬币超过限制,说明第一枚硬币至少放 d1+1 个,其他不受限制,那么方案就是 f[s−(d1+1)s1] 。别的情况同理。
示例程序
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long LL; const int maxv=100000; int te,w[4],s[4],v;LL f[maxv+5],ans; void Dfs(int st,int tot=0,int now=v) { if (st==4) {if (tot&1) ans-=f[now]; else ans+=f[now];return;} if ((s[st]+1)*w[st]<=now) Dfs(st+1,tot+1,now-(s[st]+1)*w[st]); Dfs(st+1,tot,now); } int main() { freopen("program.in","r",stdin); freopen("program.out","w",stdout); scanf("%d%d%d%d",&w[0],&w[1],&w[2],&w[3]);f[0]=1; for (int i=0;i<4;i++) for (int j=w[i];j<=maxv;j++) f[j]+=f[j-w[i]]; for (scanf("%d",&te);te;te--) { scanf("%d%d%d%d%d",&s[0],&s[1],&s[2],&s[3],&v); ans=0;Dfs(0);printf("%lld\n",ans); } return 0; }
相关文章推荐
- BZOJ1042(HAOI2008)[硬币购物]--背包+容斥
- BZOJ1042 [HAOI2008]硬币购物 【完全背包 + 容斥】
- BZOJ1042 [HAOI2008]硬币购物 【完全背包 + 容斥】
- BZOJ1042:硬币购物(背包 & 容斥)
- [BZOJ1042][HAOI2008]硬币购物(背包+容斥)
- 【bzoj1042】[HAOI2008]硬币购物 背包dp+容斥原理
- BZOJ 1042:[HAOI2008]硬币购物 容斥原理 背包dp
- BZOJ 1042: [HAOI2008]硬币购物( 背包dp + 容斥原理 )
- 【bzoj1042】 HAOI2008硬币购物 容斥原理+背包dp
- 【BZOJ1042】【DP + 容斥】[HAOI2008]硬币购物
- BZOJ 1042 HAOI2008 硬币购物 背包+容斥原理
- [bzoj1042][HAOI2008]硬币购物【dp】【容斥】
- [BZOJ 1042][HAOI 2008]硬币购物(背包+容斥原理)
- BZOJ 1042 硬币购物(完全背包+DP)
- Bzoj 1042: [HAOI2008]硬币购物 容斥原理,动态规划,背包dp
- 【BZOJ-1042】硬币购物 容斥原理 + 完全背包
- [BZOJ 1042] [HAOI2008] 硬币购物 【DP + 容斥】
- BZOJ 1042: [HAOI2008]硬币购物 DP,与处理,容斥
- [BZOJ]1042 硬币购物(HAOI2008)
- BZOJ_1042_[HAOI2008]硬币购物_容斥原理+背包