• Powerful Discount Tickets(贪心,数学)


    题意

    \(N\)件物品,每件物品价格为\(A_i\)元。

    你现在有\(K\)张优惠券。对于一个价格为\(X\)的物品,如果你使用\(y\)张优惠券,则你需要花费\(\lfloor \frac{X}{2^y} \rfloor\)元。

    求购买所有物品需要花费多少元钱?

    题目链接:https://atcoder.jp/contests/abc141/tasks/abc141_d

    数据范围

    \(1 \leq N, K \leq 10^5\)

    思路

    我们可以观察一下\(\lfloor \frac{X}{2^0} \rfloor\)\(\lfloor \frac{X}{2^1} \rfloor\)\(\lfloor \frac{X}{2^2} \rfloor\)\(\dots\)的结果。我们可以发现变化幅度是减小的,也就是将优惠券用在价格更高的物品上更好。

    因此,我们可以考虑每次使用一张优惠券,用在当前价格最高的物品上,然后该物品价格除以\(2\)。这个过程可以使用优先队列进行维护。

    这个做法为什么是正确的呢?因为这里有一条性质:对于任意正整数\(X, b_1, b_2\),有\(\lfloor \frac{\lfloor \frac{X}{b_1} \rfloor}{b_2} \rfloor = \lfloor \frac{X}{b_1 b_2} \rfloor\)

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    
    using namespace std;
    
    typedef long long ll;
    
    int n, k;
    
    int main()
    {
        priority_queue<int> que;
        scanf("%d%d", &n, &k);
        for(int i = 1; i <= n; i ++) {
            int x;
            scanf("%d", &x);
            que.push(x);
        }
        while(k --) {
            int t = que.top();
            que.pop();
            que.push(t / 2);
        }
        ll ans = 0;
        while(que.size()) {
            int t = que.top();
            ans += (ll)t;
            que.pop();
        }
        printf("%lld\n", ans);
        return 0;
    }
    
  • 相关阅读:
    关于QTTabBar的使用
    Delay, Sleep, Pause, & Wait in JavaScript
    highly recommended javascript books
    How to get the current script element
    MDX格式的字典制作
    while循环体的新用法
    printf函数的标准表达式
    C语言生成随机数代码
    C语言数组代码,小明摘苹果
    几个简单常用的C语言函数
  • 原文地址:https://www.cnblogs.com/miraclepbc/p/16408853.html
Copyright © 2020-2023  润新知