zoukankan      html  css  js  c++  java
  • [HAOI 2008]硬币购物

    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

    题解

    显然直接用多重背包做会超时,先不考虑每种硬币数量的限制,设$f[i]$为不考虑每种硬币数量的限制时,面值为$i$的方案数,则状态转移方程就呼之欲出了:$f[i]={sum f[i-c[k]]}$,$i-c[k]>=0$,$1<=k<=4$

    为避免方案重复,要以$k$为阶段递推,边界条件为$f[0]=1$,这样预处理的时间复杂度就是$O(s)$。

    接下来对于每次询问,根据容斥原理,答案即为得到面值为$S$的不超过限制的方案数=得到面值$S$的无限制的方案数即$f[s]$

    – 第$1$种硬币超过限制的方案数 – 第$2$种硬币超过限制的方案数 – 第$3$种硬币超过限制的方案数 – 第$4$种硬币超过限制的方案数

    + 第$1$,$2$种硬币同时超过限制的方案数 + 第$1$,$3$种硬币同时超过限制的方案数 + …… + 第$1$,$2$,$3$,$4$种硬币全部同时超过限制的方案数。

    用$dfs$实现,当选择的个数是奇数时用减号否则用加号。

    当第$1$种硬币超过限制时,只要要用到$D[1]+1$枚硬币,剩余的硬币可以任意分配,所以方案数为 $F[ S – (D[1]+1)*C[1] ]$,

    当且仅当$(S – (D[1]+1)*C[1])>=0$,否则方案数为$0$。其余情况类似,每次询问只用问$16$次,所以询问的时间复杂度为$O(1)$。

     1 //It is made by Awson on 2017.9.24
     2 #include <set>
     3 #include <map>
     4 #include <cmath>
     5 #include <ctime>
     6 #include <queue>
     7 #include <stack>
     8 #include <vector>
     9 #include <string>
    10 #include <cstdio>
    11 #include <cstdlib>
    12 #include <cstring>
    13 #include <iostream>
    14 #include <algorithm>
    15 #define LL long long
    16 #define Min(a, b) ((a) < (b) ? (a) : (b))
    17 #define Max(a, b) ((a) > (b) ? (a) : (b))
    18 #define lowbit(x) ((x)&(-(x)))
    19 using namespace std;
    20 const LL N = 100000;
    21 LL Read() {
    22     char ch = getchar();
    23     LL sum = 0;
    24     while (ch < '0' || ch > '9') ch = getchar();
    25     while (ch >= '0' && ch <= '9') sum = (sum<<3)+(sum<<1)+ch-48, ch = getchar();
    26     return sum;
    27 }
    28 LL c[4], k;
    29 LL f[N+5];
    30 LL d[4], s;
    31 LL ans;
    32 
    33 void dfs(int cen, LL cnt, bool mark) {
    34     if (cnt < 0) return;
    35     if (cen == 4) {
    36         if (mark) ans -= f[cnt];
    37         else ans += f[cnt];
    38         return;
    39     }
    40     dfs(cen+1, cnt-c[cen]*(d[cen]+1), !mark);
    41     dfs(cen+1, cnt, mark);
    42 }
    43 
    44 void work() {
    45     f[0] = 1;
    46     for (int i = 0; i < 4; i++) {
    47         c[i] = Read();
    48         for (int j = c[i]; j <= N; j++)
    49             f[j] += f[j-c[i]];
    50     }
    51     k = Read();
    52     while (k--) {
    53         for (int i = 0; i < 4; i++)
    54             d[i] = Read();
    55         s = Read();
    56         ans = 0;
    57         dfs(0, s, 0);    
    58         printf("%lld
    ", ans);
    59     }
    60 }
    61 int main() {
    62     work();
    63     return 0;
    64 }
  • 相关阅读:
    centos6 python 安装 sqlite 解决 No module named ‘_sqlite3′
    Python--Virtualenv简明教程
    【centos】 error: command 'gcc' failed with exit status 1
    python3.5学习笔记:linux6.4 安装python3 pip setuptools
    Python的虚拟环境virtualenv
    hdu Robberies
    转载:hdu 动态规划题集
    在Eclipse中配置Tomcat 创建和运行Servlet/JSP
    opengl中层次建模的实现
    shiyan2
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/7588590.html
Copyright © 2011-2022 走看看