bzoj 1042[HAOI2008]硬币购物 - 背包dp + 容斥原理

1042: [HAOI2008]硬币购物

Time Limit: 10 Sec  Memory Limit: 162 MB

Description

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

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
 
感觉智商收到了侮辱  <+_+>
面值只有四种,但是数量是有限的,所以我们可以用容斥原理
ans = 总的 - 至少一种超出限制 + 至少两种超出限制 - 至少三种超出限制 + 至少四种超出限制
只需要把f预处理就可以了
 
 
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #define LL long long
 6 
 7 using namespace std;
 8 
 9 const int MAXS = 1e5;
10 int c[5];
11 int S;
12 int d[5];
13 LL f[MAXS + 10];
14 int tot;
15 inline LL read()
16 {
17     LL x = 0, w = 1; char ch = 0;
18     while(ch < '0' || ch > '9') {
19         if(ch == '-') {
20             w = -1;
21         }
22         ch = getchar();
23     }
24     while(ch >= '0' && ch <= '9') {
25         x = x * 10 + ch - '0';
26         ch = getchar();
27     }
28     return x * w;
29 }
30 
31 int num = 0;
32 
33 void init()
34 {
35     f[0] = 1;
36     for(int j = 1; j <= 4;    j++) {
37         for(int i = 0; i <= MAXS; i++) {
38             if(i >= c[j]) {
39                 f[i] += f[i - c[j]];
40             }
41         }
42     }
43 }
44 
45 void cal()
46 {
47     LL ans = 0;
48     for(int i = 0; i < 16; i++) {
49         int num = 1, t = S;
50         for(int j = 1; j <= 4; j++) {
51             if(((1 << (j - 1)) & i) != 0) {
52                 num = num * -1;
53                 t -= (d[j] + 1) * c[j];
54             }
55         }
56         //cout<<num<<" "<<i<<" "<<t<<endl;
57         if(t >= 0) {
58             ans = ans + num * f[t];
59         }
60     }
61     printf("%lld\n", ans);
62 }
63 int main()
64 {
65     for(int i = 1; i <= 4; i++) {
66         c[i] = read();
67     }
68     init();
69     tot = read();
70     while(tot--) {
71         for(int i = 1; i <= 4; i++) {
72             d[i] = read();
73         }
74         S = read();
75         cal();
76     }
77     return 0;
78 }
79 
80 /*
81 1 2 5 10 2
82 
83 3 2 3 1 10
84 
85 1000 2 2 2 900
86 
87 */
View Code

 

posted @ 2018-02-27 21:50  大财主  阅读(142)  评论(0编辑  收藏  举报