BZOJ 1042 硬币购物(完全背包+DP)
2014-06-20 17:01
393 查看
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1042
题意:给出四种面值的硬币c1,c2,c3,c4。n个询问。每次询问用d1、d2、d3、d4个相应的硬币能够拼出多少种总和为s?
思路:(1)首先,用完全背包求出f[i]表示四种硬币的数量无限制拼出i的方案数。
(2)接着我们来理解 x=f[s]-f[s-(d1+1)*c1]的含义:x表示c1硬币的数量不超过d1个而其他三种硬币的数量不限制拼成s的方案数。我们举着例子来说明, 假设现在有两种硬币,面值分别为1和2,那么我们求出 f:f[0]=1,f[1]=1,f[2]=2,f[3]=2,f[4]=3,f[5]=3,f[6]=4。其中f[3]的两种分别为 3=1+1+1=1+2,f[6]的四种为:6=1+1+1+1+1+1=1+1+1+1+2=1+1+2+2=2+2+2。加入我们现在求第一种硬币最 多使用两个,第二种硬币无限制的方案数,按照我们说的x=f[6]-f[6--(2+1)*1]=f[6]-f[3]=2。也就是 6=1+1+2+2=2+2+2两种。我们发现我们删除了1+1+1+1+1+1和1+1+1+1+2两种,为什么能够通过减去f[3]删掉这两种?我们 来看f[3],3=1+1+1=1+2,我们发现6中被删掉的两种正是通过这个f[3]增加3个1得到的。
(3)现在根据我们使用完全背包求出的f 值,是没有考虑每种使用的数量,但是现在有了di的限制,我们就要减去那些不满足限制的。我们用一个4位的二进制表示状态的话,每位上为1表示第i种硬币 的数量满足不超过di的限制,那么我们就是要得到1111,而我们求出的f[s]其实是0000,那么我们怎么由0000得到1111呢?容斥原 理:1111=0000-(1000+0100+0010+0001)+ (1100+1010+1001+0110+0101+0011)-(1110+1101+1011+0111)+(1111)。
题意:给出四种面值的硬币c1,c2,c3,c4。n个询问。每次询问用d1、d2、d3、d4个相应的硬币能够拼出多少种总和为s?
思路:(1)首先,用完全背包求出f[i]表示四种硬币的数量无限制拼出i的方案数。
(2)接着我们来理解 x=f[s]-f[s-(d1+1)*c1]的含义:x表示c1硬币的数量不超过d1个而其他三种硬币的数量不限制拼成s的方案数。我们举着例子来说明, 假设现在有两种硬币,面值分别为1和2,那么我们求出 f:f[0]=1,f[1]=1,f[2]=2,f[3]=2,f[4]=3,f[5]=3,f[6]=4。其中f[3]的两种分别为 3=1+1+1=1+2,f[6]的四种为:6=1+1+1+1+1+1=1+1+1+1+2=1+1+2+2=2+2+2。加入我们现在求第一种硬币最 多使用两个,第二种硬币无限制的方案数,按照我们说的x=f[6]-f[6--(2+1)*1]=f[6]-f[3]=2。也就是 6=1+1+2+2=2+2+2两种。我们发现我们删除了1+1+1+1+1+1和1+1+1+1+2两种,为什么能够通过减去f[3]删掉这两种?我们 来看f[3],3=1+1+1=1+2,我们发现6中被删掉的两种正是通过这个f[3]增加3个1得到的。
(3)现在根据我们使用完全背包求出的f 值,是没有考虑每种使用的数量,但是现在有了di的限制,我们就要减去那些不满足限制的。我们用一个4位的二进制表示状态的话,每位上为1表示第i种硬币 的数量满足不超过di的限制,那么我们就是要得到1111,而我们求出的f[s]其实是0000,那么我们怎么由0000得到1111呢?容斥原 理:1111=0000-(1000+0100+0010+0001)+ (1100+1010+1001+0110+0101+0011)-(1110+1101+1011+0111)+(1111)。
int n,c[5],d[5],s; i64 f ,ans; void DP() { f[0]=1; int i,j; FOR1(i,4) for(j=c[i];j<N;j++) { f[j]+=f[j-c[i]]; } } i64 F(int x) { if(x>=0) return f[x]; return 0; } int main() { int i,j,k; FOR1(i,4) RD(c[i]); DP(); RD(n); while(n--) { FOR1(i,4) RD(d[i]),d[i]=(d[i]+1)*c[i]; RD(s); ans=F(s); FOR1(i,4) ans-=F(s-d[i]); FOR1(i,4) FOR(j,i+1,4) ans+=F(s-d[i]-d[j]); FOR1(i,4) FOR(j,i+1,4) FOR(k,j+1,4) ans-=F(s-d[i]-d[j]-d[k]); ans+=F(s-d[1]-d[2]-d[3]-d[4]); PR(ans); } return 0; }
相关文章推荐
- Bzoj 1042: [HAOI2008]硬币购物 容斥原理,动态规划,背包dp
- BZOJ1042 [HAOI2008]硬币购物 【完全背包 + 容斥】
- BZOJ1042 [HAOI2008]硬币购物 【完全背包 + 容斥】
- 【BZOJ-1042】硬币购物 容斥原理 + 完全背包
- 【bzoj1042】 HAOI2008硬币购物 容斥原理+背包dp
- BZOJ 1042: [HAOI2008]硬币购物( 背包dp + 容斥原理 )
- BZOJ 1042:[HAOI2008]硬币购物 容斥原理 背包dp
- 【背包+容斥】BZOJ1042(HAOI2008)[硬币购物]题解
- bzoj 1042: [HAOI2008]硬币购物【dp】
- [BZOJ1042][HAOI2008]硬币购物(背包+容斥)
- BZOJ1042:硬币购物(背包 & 容斥)
- 【bzoj1042】[HAOI2008]硬币购物【dp预处理+容斥】
- BZOJ 1042 HAOI2008 硬币购物 背包+容斥原理
- [bzoj 1042][HAOI2008]硬币购物(用容斥原理弄背包)
- BZOJ 1042: [HAOI2008]硬币购物 DP,与处理,容斥
- BZOJ_1042_[HAOI2008]硬币购物_容斥原理+背包
- BZOJ1042(HAOI2008)[硬币购物]--背包+容斥
- [BZOJ 1042][HAOI 2008]硬币购物(背包+容斥原理)
- BZOJ-1042 [HAOI2008]硬币购物 容斥原理 +01背包方案数
- 【bzoj1042】[HAOI2008]硬币购物 背包dp+容斥原理