[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 个限制条件 x[i] <= d[i] .

  假如没有使用个数的限制, 我们可以通过背包 DP 进行预处理, f[s] 表示凑出 s 的方案数.

  条件取并, 我们尝试用减法原理 + 容斥原理进行转化.

  用 f[s] 减去满足一个 "x[i] > d[i]" 的限制条件的解的个数, 加上满足两个 "x[i] > d[i]" 的限制条件的解的个数, 减去满足三个 "x[i] > d[i]" 的限制条件的解的个数, 加上满足四个 "x[i] > d[i]" 的限制条件的解的个数.

  问题转化为计算满足若干个 "x[i] > d[i]" 的限制条件的解的个数.

  令 x[i] = y[i] + d[i] + 1 , 那么这一项的贡献为 c[i]x[i] = c[i]y[i] + c[i](d[i] + 1) , 令 s 减去 c[i](d[i]+1) , 那么就变成了没有限制使用个数的问题.

实现

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cctype>
 5 #define F(i, a, b) for (register int i = (a); i <= (b); i++)
 6 #define LL long long
 7 inline int rd(void) {
 8     int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -1;
 9     int x = 0; for (; isdigit(c); c = getchar()) x = x*10+c-‘0‘; return x*f;
10 }
11
12 const int S = 100000;
13
14 LL c[4], f[S+5];
15 inline LL G(LL n) { return 0 <= n && n <= S ? f[n] : 0; }
16
17 int main(void) {
18     #ifndef ONLINE_JUDGE
19         freopen("bzoj1042.in", "r", stdin);
20     #endif
21
22     f[0] = 1;
23     F(i, 0, 3) {
24         c[i] = rd();
25         F(j, c[i], S) f[j] += f[j - c[i]];
26     }
27
28     int n = rd();
29     F(t, 1, n) {
30         LL d0 = (rd()+1) * c[0], d1 = (rd()+1) * c[1], d2 = (rd()+1) * c[2], d3 = (rd()+1) * c[3], s = rd();
31         LL res = G(s);
32         res = res - G(s - d0) - G(s - d1) - G(s - d2) - G(s - d3);
33         res = res + G(s - d0 - d1) + G(s - d0 - d2) + G(s - d0 - d3) + G(s - d1 - d2) + G(s - d1 - d3) + G(s - d2 - d3);
34         res = res - G(s - d0 - d1 - d2) - G(s - d0 - d1 - d3) - G(s - d0 - d2 - d3) - G(s - d1 - d2 - d3);
35         res = res + G(s - d0 - d1 - d2 - d3);
36         printf("%lld\n", res);
37     }
38
39     return 0;
40 }
时间: 2024-10-01 07:17:54

[BZOJ 1042] 硬币购物 容斥原理的相关文章

BZOJ 1042 硬币购物(完全背包+DP)

题目链接: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的方案数.我们举着例子来说明, 假设

BZOJ 1042 硬币购物

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

[BZOJ]1042 硬币购物(HAOI2008)

失踪OJ回归. 小C通过这道题mark一下容斥一类的问题. Description 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买s的价值的东西.请问每次有多少种付款方法. Input 第一行 c1,c2,c3,c4,tot 下面tot行 d1,d2,d3,d4,s. Output 每次的方法数. Sample Input 1 2 5 10 2 3 2 3 1 10 1000 2 2 2 900 Sample Output 4

[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]硬币购物 容斥原理

题意:链接 方法:容斥原理 解析:简单题,不掉坑都对不起我自己 这题很好想的一个容斥原理,因为一共只有四种硬币,我们不方便计算满足题中要求的方案数,但是从反向思考,我们需要做的就是减掉奇数个硬币用超额的情况,然后加上偶数个硬币用超额的情况就是最终的答案(当然状态是0000的时候看做是一个基准). 然后我没什么说的了,只是有一些细节需要注意下: 1.要用long long 2.完全背包千万不要傻到每次重新背,直接一次预处理就好,不过我为什么要重新背啊!(差了8s) 代码: #include <cs

BZOJ 1042 HAOI 2008 硬币购物 容斥原理

题目大意:给出4个硬币的价值和个数限制,求有多少种方法凑成S块钱. 思路:很巧妙的一种想法,用到了4这个非常小的数字.我们可以先不管每个硬币的个数限制,然后跑一次完全背包.之后把不符合的情况去除就行了.方法是,先减去一种硬币超限的数目,然后加上两种硬币超限的数目,然后减去三种硬币超限的数目,然后加上四种硬币超限的个数.当然代码就很丑了.. CODE: #include <cstdio> #include <cstring> #include <iostream> #in

BZOJ 1042 HAOI2008 背包+容斥原理

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

bzoj 1042: [HAOI2008]硬币购物 dp+容斥原理

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

【BZOJ】【1042】【HAOI2008】硬币购物

DP+容斥原理 sigh……就差一点…… 四种硬币的数量限制就是四个条件,满足条件1的方案集合为A,满足条件2的方案集合为B……我们要求的就是同时满足四个条件的方案集合$A\bigcap B\bigcap C\bigcap D$的大小. 全集很好算……一个完全背包>_>$4×10^5$就可以预处理出来…… 然后我sb地去算满足一个条件.两个条件……的方案数去了QAQ根本算不出来啊 orz了hzwer的题解,其实是算 不满足一个条件.不满足两个条件…的方案数的,因为如果第一种硬币超了,说明用了d