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

    题目描述
    硬币购物一共有4种硬币。面值分别为c1,c2,c3,c4。某人去商店买东西,去了tot次。每次带di枚ci硬币,买si的价值的东西。请问每次有多少种付款方法。

    di,s<=100000

    tot<=1000

    Solution

    完全背包数组开不下, 大概要运算一天这样能出答案
    假设没有带硬币的限制, 我们可以搞个完全背包算出 (maxn) 内每个的方案数, 就可以 (O(1)) 回答询问了
    问题是如何解决这个限制问题

    对于第 (i) 个硬币, 我们只能拿 (d_{i} * c_{i}) 这么多钱
    那就是说如果我拿了 ((d_{i} + 1) * c[i]) 这么多钱则剩下的不合法
    那么 (dp[S - (d_{i} + 1) * c[i]]) 便不合法
    然后发现这样可能会减掉重复的
    容斥一下, 减去单数个的加上偶数个的
    只有 4 枚硬币, 可以状压枚举状态(0 - 15), 模拟做容斥即可
    说不明白的可以看代码

    Code

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #include<climits>
    #define LL long long
    #define REP(i, x, y) for(LL i = (x);i <= (y);i++)
    using namespace std;
    LL RD(){
        LL out = 0,flag = 1;char c = getchar();
        while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
        while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
        return flag * out;
        }
    const LL maxn = 200019;
    LL c[7], T;//7777777
    LL d[7], one[7], S;
    LL dp[maxn];
    void init(){
        REP(i, 1, 4)c[i] = RD(), one[i] = 1 << (i - 1);
        dp[0] = 1;
        REP(i, 1, 4){
            REP(j, c[i], maxn - 7){
                dp[j] += dp[j - c[i]];
                }
            }
        T = RD();
        }
    void solve(){
        while(T--){
            REP(i, 1, 4)d[i] = RD();
            S = RD();
            LL ans = 0;
            REP(i, 0, 15){//每个状态
                LL temp = S;
                LL cnt = 0;
                REP(j, 1, 4){
                    if(i & one[j])
                        temp -= (d[j] + 1) * c[j], cnt ^= 1;
                    }
                if(temp < 0)continue;
                if(!cnt)ans += dp[temp];
                else ans -= dp[temp];
                }
            printf("%lld
    ", ans);
            }
        }
    int main(){
        init();
        solve();
        return 0;
        }
    
  • 相关阅读:
    再也不买仙剑正版盘了
    如果能边睡觉边上网多好
    不服
    <转>猛兽多是懒汉
    窗体中实现按 回车键 跳到下一个可选的TabIndex控件
    c# 索引器基础理论
    软件加密技术和注册机制入门介绍
    c# 属性 
    异常的一些基础知识
    关于MessageBox.Show的使用
  • 原文地址:https://www.cnblogs.com/Tony-Double-Sky/p/9899561.html
Copyright © 2011-2022 走看看