zoukankan      html  css  js  c++  java
  • BZOJ1042:[HAOI2008]硬币购物(DP,容斥)

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

    Output

    每次的方法数

    Sample Input

    1 2 5 10 2
    3 2 3 1 10
    1000 2 2 2 900

    Sample Output

    4
    27

    Solution

    先设$f[i]$表示没有硬币数量限制的时候,花费为$i$的方案数。
    简单容斥可得,$ans=$没有限制的情况$-$一种硬币使用大于$d[i]$次的方案$+$两种硬币使用大于$d[i]$次的方案$-$三种硬币使用大于$d[i]$次的方案$+$四种硬币使用大于$d[i]$次的方案
    爆搜枚举所有情况。假设只有$c[1]$使用大于$d[1]$次,那么方案为$f[s-(d[1]+1)*c[1]]$。也就是强制先使用上$d[1]+1$枚硬币,其余的随意选。
    其他情况同理。

    Code

     1 #include<iostream>
     2 #include<cstdio>
     3 #define N (100009)
     4 #define LL long long
     5 using namespace std;
     6 
     7 LL T,s,ans,c[5],d[5],f[N];
     8 
     9 void Dfs(LL x,LL k,LL sum)
    10 {
    11     if (sum<0) return;
    12     if (x==5)
    13     {
    14         if (k&1) ans-=f[sum];
    15         else ans+=f[sum];
    16         return;
    17     }
    18     Dfs(x+1,k+1,sum-(d[x]+1)*c[x]);
    19     Dfs(x+1,k,sum);
    20 }
    21 
    22 int main()
    23 {
    24     f[0]=1;
    25     for (int i=1; i<=4; ++i)
    26     {
    27         scanf("%lld",&c[i]);
    28         for (int j=c[i]; j<=100000; ++j)
    29             f[j]+=f[j-c[i]];
    30     }
    31     scanf("%lld",&T);
    32     while (T--)
    33     {
    34         for (int i=1; i<=4; ++i)
    35             scanf("%lld",&d[i]);
    36         scanf("%lld",&s);
    37         ans=0;
    38         Dfs(1,0,s);
    39         printf("%lld
    ",ans);
    40     }
    41 }
  • 相关阅读:
    windows修复移动硬盘文件夹打不来的问题
    secureCRT设置
    core dump配置
    ssh免密登陆的问题解决
    crontab的环境变量
    tmux配置
    shell的技巧笔记
    记一次route配置不起作用的问题解决过程
    crontab笔记
    Python中的一个诡异编码问题的追踪
  • 原文地址:https://www.cnblogs.com/refun/p/9800037.html
Copyright © 2011-2022 走看看