• Bzoj 1042: [HAOI2008]硬币购物 容斥原理,动态规划,背包dp


    1042: [HAOI2008]硬币购物

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 1747  Solved: 1015
    [Submit][Status][Discuss]

    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<=1000

    Source

     题解:
    容斥原理+动态规划
    f[i]表示四种硬币个数没有限制的付款方案数。(求f[i]就是个完全背包)
    ans=不限定的方案数-(硬币1超过的方案数+硬币2超过的方案数+硬币3超过的方案数+硬币4超过的方案数)+(硬币1,2超过的方案数………………)-(硬币1,2,3超过的方案数)+(硬币1,2,3,4都超过的方案数)
    超过的方案数:
         例如:要算硬币1超过的方案数,那么我们就要让硬币1超过d[1],即为d[1]+1,则剩余价值为s-(d[1]+1)*c[1]。
    具体见程序:
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define MAXN 100000
     4 #define LL long long
     5 LL S,c[6],d[6],f[MAXN+10];
     6 LL read()
     7 {
     8     LL s=0,fh=1;char ch=getchar();
     9     while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();}
    10     while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();}
    11     return s*fh;
    12 }
    13 LL F(LL A,LL B,LL C,LL D)
    14 {
    15     LL ans=S;
    16     if(A!=0)ans-=(d[1]+1)*c[1];
    17     if(B!=0)ans-=(d[2]+1)*c[2];
    18     if(C!=0)ans-=(d[3]+1)*c[3];
    19     if(D!=0)ans-=(d[4]+1)*c[4];
    20     if(ans<0)return 0;
    21     return f[ans];
    22 }
    23 int main()
    24 {
    25     LL i,j,sum,tot;
    26     for(i=1;i<=4;i++)c[i]=read();tot=read();
    27     f[0]=1;
    28     for(i=1;i<=4;i++)
    29     {
    30         for(j=c[i];j<=MAXN;j++)f[j]+=f[j-c[i]];
    31     }
    32     while(tot--)
    33     {
    34         for(i=1;i<=4;i++)d[i]=read();S=read();
    35         sum=0;
    36         sum+=F(0,0,0,0);
    37         sum-=F(1,0,0,0);
    38         sum-=F(0,1,0,0);
    39         sum-=F(0,0,1,0);
    40         sum-=F(0,0,0,1);
    41         sum+=F(1,1,0,0);
    42         sum+=F(1,0,1,0);
    43         sum+=F(1,0,0,1);
    44         sum+=F(0,1,1,0);
    45         sum+=F(0,1,0,1);
    46         sum+=F(0,0,1,1);
    47         sum-=F(1,1,1,0);
    48         sum-=F(1,1,0,1);
    49         sum-=F(1,0,1,1);
    50         sum-=F(0,1,1,1);
    51         sum+=F(1,1,1,1);
    52         printf("%lld
    ",sum);
    53     }
    54     return 0;
    55 }
  • 相关阅读:
    获得随机N位数不重复数字
    springboot配置swagger
    Java开发中的23种设计模式详解(转)
    英文对应解释
    python实现ping命令语音播报联通性V1.0.0.1
    python实现ping命令语音播报联通性V1.0
    python实现ping命令语音播报联通性
    eclipse更新支持tomcat-8.0以上
    网管---------Windows杀死后台进程查询等脚本
    网管-windows磁盘检查修复
  • 原文地址:https://www.cnblogs.com/Var123/p/5317912.html
Copyright © 2020-2023  润新知