zoukankan      html  css  js  c++  java
  • bzoj 1042[HAOI2008]硬币购物

    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
    ", 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
  • 相关阅读:
    旧题复习{6}
    CF219D. Choosing Capital for Treeland [树形DP]
    POJ1947 Rebuilding Roads[树形背包]

    洛谷P1280 尼克的任务[DP]
    NOIP2003pj栈[卡特兰数]
    NOIP2001统计单词个数[序列DP]
    洛谷P1415 拆分数列[序列DP 状态 打印]
    POJ2828 Buy Tickets[树状数组第k小值 倒序]
    CF380C. Sereja and Brackets[线段树 区间合并]
  • 原文地址:https://www.cnblogs.com/wuenze/p/8481185.html
Copyright © 2011-2022 走看看