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

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 2468  Solved: 1478

    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

    HINT

     

    Source

    数学问题 DP  容斥

    思路好神奇啊。

    设f[i]表示不考虑硬币数量限制的情况下,凑出面值 i 的方案数。一个简单的背包就统计出来了。

    然后根据容斥原理统计:

      ans=不考虑数量限制凑出S的方案数 - c1超限制凑出S的方案数 - c2超限制凑出S的方案数 - c3超限制凑出S的方案数 - c4超限制凑出S的方案数 + c1和c2超限凑出S的方案数 +... +c1 c2 c3 c4均超限凑出S的方案数。

    c1超出限制凑出S的方案数= f[S-(d[1]+1)*c[1]]  (c1至少超出了1枚,剩余面值可以用任意硬币)

    其他类似。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<queue>
     6 #define LL long long
     7 using namespace std;
     8 const int mxn=100010;
     9 int read(){
    10     int x=0,f=1;char ch=getchar();
    11     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    12     while(ch>='0' && ch<='9'){x=x*10-'0'+ch;ch=getchar();}
    13     return x*f;
    14 }
    15 int c[5],d[5],S;
    16 LL f[mxn];
    17 inline LL F(int x){return x<0?0:f[x];}
    18 void calc(){
    19     LL ans=F(S);
    20     for(int i=1;i<=4;i++)
    21         ans-=F(S-(d[i]+1)*c[i]);
    22     for(int i=1;i<=4;i++)
    23         for(int j=i+1;j<=4;j++)
    24             ans+=F(S-(d[i]+1)*c[i]-(d[j]+1)*c[j]);
    25     ans-=F( S-(d[1]+1)*c[1]-(d[2]+1)*c[2]-(d[3]+1)*c[3] );
    26     ans-=F( S-(d[1]+1)*c[1]-(d[2]+1)*c[2]-(d[4]+1)*c[4] );
    27     ans-=F( S-(d[1]+1)*c[1]-(d[3]+1)*c[3]-(d[4]+1)*c[4] );
    28     ans-=F( S-(d[2]+1)*c[2]-(d[3]+1)*c[3]-(d[4]+1)*c[4] );
    29     ans+=F( S-(d[1]+1)*c[1]-(d[2]+1)*c[2]-(d[3]+1)*c[3]-(d[4]+1)*c[4] );
    30     printf("%lld
    ",ans);
    31     return;
    32 }
    33 int main(){
    34     int i,j;
    35     f[0]=1;
    36     for(i=1;i<=4;i++){
    37         c[i]=read();
    38         for(j=c[i];j<mxn;j++)f[j]+=f[j-c[i]];
    39     }
    40     int T=read();
    41     while(T--){
    42         for(i=1;i<=4;i++)d[i]=read();
    43         S=read();
    44         calc();
    45     }
    46     return 0;
    47 }
  • 相关阅读:
    C#中class的访问级别
    Install-Package 那点事儿
    Gherkin学习笔记
    mysql-connector-c 安装
    shell实现死循环
    每天一个小算法(6)---- 通过两个栈实现一个队列
    每天一个小算法(5)----找到链表倒数第K个结点
    每天一个小算法(4)----在O(1)时间删除指定结点
    每天一个小算法(3)----倒序打印链表
    每天一个小算法(2)----合并两个有序链表
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6896307.html
Copyright © 2011-2022 走看看