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

    1042: [HAOI2008]硬币购物

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 2648  Solved: 1609
    [Submit][Status][Discuss]

    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
    分析:可以用背包来做,但是会超时,可以考虑容斥原理。题目要我们求满足所有条件的方案数,那么我们可以用第二条容斥原理,即所有方案数-不满足一条的方案数+不满足两条的方案数-不满足三条的方案数......,可以利用dfs解决。如果第i个硬币不满足条件,则这个硬币用d[i]+1个,统计一下就好了.
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    long long c[5], tot,d[5],s,ans,f[100010];
    
    void dfs(int cnt, long long n,int k)
    {
        if (cnt == 5)
        {
            ans += f[n] * k;
            return;
        }
        if (c[cnt] * (d[cnt] + 1) <= n)
        dfs(cnt + 1, n - c[cnt] * (d[cnt] + 1), -k);
        dfs(cnt + 1, n, k);
    }
    
    int main()
    {
        scanf("%lld%lld%lld%lld%lld", &c[1], &c[2], &c[3], &c[4], &tot);
        f[0] = 1;
        for (int i = 1; i <= 4; i++)
            for (int j = c[i]; j <= 100000; j++)
                f[j] += f[j - c[i]];
        while (tot--)
        {
            ans = 0;
            scanf("%lld%lld%lld%lld%lld", &d[1], &d[2], &d[3], &d[4], &s);
            dfs(1,s,1);
            printf("%lld
    ", ans);
        }
    
        return 0;
    }
  • 相关阅读:
    spring揭秘 读书笔记 六 bean的一生
    分枝限界算法
    libLAS1.8.0 编译和配置(VS2013+Win7 64)(一)
    Unity学习笔记 之 发射小球碰撞物体的代码记录
    hdu1281 棋盘游戏 --- 最大匹配
    javascript设计模式
    3、Android中Activity的跳转
    2.11 确定运行计划
    php扩展之 pdo_mysql.so
    POJ 1061 青蛙的约会(扩展欧几里得)
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7289425.html
Copyright © 2011-2022 走看看