bzoj1042--容斥原理+完全背包

题目大意:

硬币购物一共有4种硬币。面值分别为c1,c2,c3,c4。某人去商店买东西,去了tot次。每次带di枚ci硬币,买si的价值的东西。请问每次有多少种付款方法。其中di,s<=100000,tot<=1000

思路:
先用完全背包求出如果每种硬币可以用无数次的方案数,再容斥一下就好了。

具体看代码。

代码:

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<algorithm>
 5 using namespace std;
 6 #define ll long long
 7 int i,j,k,n,m,tot,c[4],d[4],s;
 8 ll f[100001],ans;
 9 bool b[4];
10 inline ll S(){
11     int tmp=s;
12     for(int i=0;i<4;i++)if(b[i])tmp-=c[i]*(d[i]+1);
13     if(tmp<0)return 0;else return f[tmp];
14 }
15 inline void dfs(int x,int sum){
16     if(x==4){
17         if(sum==0)return;
18         if(sum&1)ans-=S();else ans+=S();
19         return;
20     }
21     dfs(x+1,sum);
22     b[x]=1;
23     dfs(x+1,sum+1);
24     b[x]=0;
25 }
26 int main()
27 {
28     for(i=0;i<4;i++)scanf("%d",&c[i]);scanf("%d",&tot);
29     for(f[0]=1,i=0;i<4;i++)
30     for(j=c[i];j<=100000;j++)
31     f[j]+=f[j-c[i]];
32     while(tot--){
33         for(i=0;i<4;i++)scanf("%d",&d[i]);
34         scanf("%d",&s);
35         ans=f[s];
36         dfs(0,0);
37         printf("%lld\n",ans);
38     }
39     return 0;
40 }

bzoj1042

时间: 2024-11-03 21:40:02

bzoj1042--容斥原理+完全背包的相关文章

【bzoj1042】[HAOI2008]硬币购物 背包dp+容斥原理

题目描述 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买si的价值的东西.请问每次有多少种付款方法. 输入 第一行 c1,c2,c3,c4,tot 下面tot行 d1,d2,d3,d4,s,其中di,s<=100000,tot<=1000 输出 每次的方法数 样例输入 1 2 5 10 2 3 2 3 1 10 1000 2 2 2 900 样例输出 4 27 题解 背包dp+容斥原理 考虑没有硬币个数限制,那么本题显然是完全

BZOJ-1042: [HAOI2008]硬币购物 (背包DP+容斥原理)

1042: [HAOI2008]硬币购物 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2888  Solved: 1777[Submit][Status][Discuss] Description 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买si的价值的东西.请问每次有多少种付款方法. Input 第一行 c1,c2,c3,c4,tot 下面tot行 d1,d2,d3,d4,

[BZOJ 1042][HAOI 2008]硬币购物(背包+容斥原理)

题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1042 刚开始搞容斥原理,还很有点吃力,我太弱了... 首先用被类似于背包的DP进行预处理,假设每种硬币个数无限制,求出f[i]=凑出面值i的方案总数. 但是实际上题目中每种硬币个数是有限制的,设四种硬币分别是a.b.c.d,则凑出面值S的方案中超出限制的方案数=a超出限制的方案数+b超出限制的方案数+c超出限制的方案数+d超出限制的方案数-a和b都超出限制的方案数-a和c都超出限

[bzoj1042][HAOI2008][硬币购物] (容斥原理+递推)

Description 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买si的价值的东西.请问每次有多少种付款方法. Input 第一行 c1,c2,c3,c4,tot 下面tot行 d1,d2,d3,d4,s,其中di,s<=100000,tot<=1000 Output 每次的方法数 Sample Input 1 2 5 10 2 3 2 3 1 10 1000 2 2 2 900 Sample Output 4 27 So

BZOJ 1042 HAOI2008 背包+容斥原理

题目大意:给定4种硬币的面值,多次询问这个限定这四种硬币的个数时达到某一价值的方案数 十分巧妙的一个题--蒟蒻表示打死也想不到容斥原理0.0 首先先求出不限定硬币的方案数 然后利用容斥原理 ans=不限定硬币的方案数-(硬币1超出的方案数+硬币2超出的方案数+硬币3超出的方案数+硬币4超出的方案数)+(硬币1和硬币2都超出的方案数+--)-(硬币123都超出的方案数+--)+四种硬币都超出的方案数 超出的方案数怎么求呢?比如说我们想要硬币1超出,那么我们需要有至少d1+1个硬币1 剩余的价值是s

BZOJ_1042_[HAOI2008]硬币购物_容斥原理+背包

题意: 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买s i的价值的东西.请问每次有多少种付款方法. 分析: 假设没有di的限制,先跑一遍完全背包 容斥,用总方案数减去有一种硬币数目不合法的方案数加上有两种硬币不合法的方案数...... 怎么求这个方案数呢? 我们发现如果第i种硬币数目不合法,那它一定拿了至少(di+1)个,方案数就是f[n-(di+1)*ci] 代码: #include <cstdio> #include &

[BZOJ 1042] 硬币购物 容斥原理

题意 有四种货币, 它们的价值分别是 c[0], c[1], c[2], c[3] . n 次询问, 每次给定 d[0], d[1], d[2], d[3], s, 问凑出 s , 且第 i 种货币不超过 c[i] 个的方案数. c[i], d[i], s <= 100000 , n <= 1000 . 分析 设第 i 种货币取了 x[i] 个. 问题转化为求不定方程 c[0]x[0] + c[1]x[1] + c[2]x[2] + c[3]x[3] = s 的非负整数解的个数. 且满足 4

【bzoj1042】 HAOI2008—硬币购物

http://www.lydsy.com/JudgeOnline/problem.php?id=1042 (题目链接) 题意:共有4种硬币,面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买s的价值的东西.请问每次有多少种付款方法. Solution  容斥原理.  设F[i]为不考虑每种硬币的数量限制的情况下,得到面值i的方案数.则状态转移方程为 F[i]=Sum{F[i-C[k]] | i-C[k]>=0 且 k=1..4} ,边界条件F[0]=0. 

BZOJ1042

传送门:BZOJ1042 首先,计算出购买面值为i的物品的方案数f(i),这一步强制有序就可以了. 然后,每一次查询时ans=(f(s)-d1溢出方案-d2-+d1d2+d2d3+--d1d2d3-.+d1d2d3d4),即容斥原理. 注意到d1溢出时,至少使用了d1+1个物品,于是剩下S-(d1+1)c1都可以随意分配,于是d1溢出的方案就是f(S-(d1+1)c1) 代码上的小细节见下. #include <cstdio> #include <cstdlib> #include