cf Educational Codeforces Round 127 C. Dolce Vita

原题:

C. Dolce Vita
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Turbulent times are coming, so you decided to buy sugar in advance. There are n shops around that sell sugar: the i − t h i-th ith shop sells one pack of sugar for a i a_i ai coins, but only one pack to one customer each day. So in order to buy several packs, you need to visit several shops.

Another problem is that prices are increasing each day: during the first day the cost is a i a_i ai, during the second day cost is a i + 1 a_i+1 ai+1, during the third day — a i + 2 a_i+2 ai+2 and so on for each shop i i i.

On the contrary, your everyday budget is only x coins. In other words, each day you go and buy as many packs as possible with total cost not exceeding x. Note that if you don’t spend some amount of coins during a day, you can’t use these coins during the next days.

Eventually, the cost for each pack will exceed x, and you won’t be able to buy even a single pack. So, how many packs will you be able to buy till that moment in total?

Input

The first line contains a single integer t (1≤t≤1000) — the number of test cases. Next t cases follow.

The first line of each test case contains two integers n and x (1≤n≤ 2 × 1 0 5 2×10^5 2×105; 1≤x≤ 1 0 9 10^9 109) — the number of shops and your everyday budget.

The second line of each test case contains n integers a1,a2,…,an (1≤ a i a_i ai 1 0 9 10^9 109) — the initial cost of one pack in each shop.

It’s guaranteed that the total sum of n doesn’t exceed 2 × 1 0 5 2×10^5 2×105.
Output

For each test case, print one integer — the total number of packs you will be able to buy until prices exceed your everyday budget.

Example
Input

4
3 7
2 1 2
5 9
10 20 30 40 50
1 1
1
2 1000
1 1

Output
Copy

11
0
1
1500

Note

In the first test case,

Day 1: prices are [2,1,2]. You can buy all 3 packs, since 2+1+2≤7.
Day 2: prices are [3,2,3]. You can’t buy all 3 packs, since 3+2+3>7, so you buy only 2 packs.
Day 3: prices are [4,3,4]. You can buy 2 packs with prices 4 and 3.
Day 4: prices are [5,4,5]. You can’t buy 2 packs anymore, so you buy only 1 pack.
Day 5: prices are [6,5,6]. You can buy 1 pack.
Day 6: prices are [7,6,7]. You can buy 1 pack.
Day 7: prices are [8,7,8]. You still can buy 1 pack of cost 7.
Day 8: prices are [9,8,9]. Prices are too high, so you can’t buy anything.

In total, you bought 3+2+2+1+1+1+1=11 packs.

In the second test case, prices are too high even at the first day, so you can’t buy anything.

In the third test case, you can buy only one pack at day one.

In the fourth test case, you can buy 2 packs first 500 days. At day 501 prices are [501,501], so you can buy only 1 pack the next 500 days. At day 1001 prices are [1001,1001] so can’t buy anymore. In total, you bought 500⋅2+500⋅1=1500 packs.

中文:
最近日子不好过,你打算提前买点糖。有n个商店卖糖,第i个商店卖一包糖花费 a i a_i ai元,每家店你只能一包糖。所以为了多买几包糖,你需要多逛几个商店。
另外一个问题是这些商店的糖的价格每天都会上涨一块钱,第一天是 a i a_i ai第二天是 a i + 1 a_i + 1 ai+1
你每天的预算只有x元,每天你得买尽量多的糖,总价格不超过x,第i天买糖剩下的钱不能留到i+1天用。如果有一天你一包糖都买不了,最后统计你总共能买多少糖?

代码:

        #include <bits/stdc++.h>
        using namespace std;
        typedef long long ll;
        const int maxn = 2e5 + 5;
        ll t, n;
        ll x;
        ll a[maxn], sum[maxn];
         
         
        int main() {
            ios::sync_with_stdio(false);
            cin >> t;
            while(t--) {
                cin >> n >> x;
                for (int i = 1; i <= n; i++) {
                    cin >> a[i];
                    sum[i] = 0;
                }
                sum[0] = 0;
                sort(a + 1, a + 1 + n);
                for (int i = 1; i <= n; i++) {
                   sum[i] = sum[i-1] + a[i];
                }
                ll pre = 0, ans = 0;
                for (int i = n; i >= 1; i--) {
                    ll tmp = x - sum[i];
                    if (tmp < 0) {
                        continue;
                    }
                    int cnt = tmp / i;
                    // cout << "i = " << i << " tmp = " << tmp << " cnt = " << cnt << " pre = " << pre << endl;
                    ans += (cnt + 1 - pre) * i;
                    pre = cnt + 1;
                }
                cout << ans << endl;
            }
            return 0;
        }

解答:
思维题
来个例子,取 x = 20,a=[3,1,5,7]

首先对a排序,并计算前缀和,得到sum = [1, 4, 9, 16]。
在第一天此时20大于sum[4] (下标从1开始计算),表示可以买下4个商店的糖。
在第二天的时候,每个商店的糖价都加1,对应的前缀和为 sum = [2, 6, 12, 20],可以看到,排序后前缀和第i个下标,每次上涨的值就是i,即第1天是16,第二天就变成20了。

根据上面的规律,应用贪心的思想,将前缀和从后向前遍历,使用公式计算出sum[i]在第几天的时候会超出x。
i = 4时,公式为: s u m [ i ] + c n t × i ≤ x sum[i] + cnt × i ≤ x sum[i]+cnt×ix,即 16 + c n t × 4 ≤ 20 16 + cnt × 4 ≤ 20 16+cnt×420,此时cnt等于1,此时表示连续买前四家商店的糖,可以连续买 1 + 1 = 2 1+1=2 1+1=2天,买到的糖数时 2 × 4 = 8

当i = 3时,同样, 9 + c n t × 3 ≤ 20 9 + cnt × 3 ≤ 20 9+cnt×320 得到cnt等于3,此时要注意,i = 3时计算的买糖数量包含了i = 4时(即前一天买糖数量的前缀和),这里要将得到的结果减去i = 4时的值, 即 4 - 2 = 2,表示连续买前三家点的糖,可以连续买2天,糖数是 (4 - 2) × 3 = 6

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值