首页 > 试题广场 >

小红的口罩

[编程题]小红的口罩
  • 热度指数:1217 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
疫情来了,小红网购了 n 个口罩。
众所周知,戴口罩是很不舒服的。小红每个口罩戴一天的初始不舒适度为 a_i
小红有时候会将口罩重复使用(注:这是非常不卫生的!),每次重复使用时,该口罩的不舒适度会翻倍!
小红想知道,自己在不舒适度总和不超过 k 的情况下,最多能用现有的口罩度过多少天?

输入描述:
第一行输入两个正整数 nk ,分别代表口罩的总数、以及小红最多能忍受的不舒适度总和。
第二行输入 n 个正整数 a_i ,用空格隔开。分别代表每个口罩初始的不舒适度。


输出描述:
一个整数,代表小红最多能度过的天数。
示例1

输入

2 30
2 3

输出

5

说明

第一天用第一个口罩,不舒适度为2。
第二天用第一个口罩,不舒适度为4。
第三天用第二个口罩,不舒适度为3。
第四天用第二个口罩,不舒适度为6。
第五天用第二个口罩,不舒适度为12。
总不舒适度为2+4+3+6+12=27,没有超过30。
可以证明,无论怎样分配,都无法度过6天且不舒适度总和不超过30
示例2

输入

3 5
7 6 8

输出

0

说明

显然,使用任何一个口罩都会使不舒适度超过5。
首先我们考虑下最优的使用策略:每天从所有口罩选出不舒适值最低的,就能确保使用天数最多。
但口罩太多,每天都要浪费时间找,怎么办?

这时我们发现不舒适值的变化规则是“翻倍”,这就意味着:
如果翻倍前2n-1≤ai<2n,那么翻倍后2n≤ai<2n+1
结论1:这些区间是连续的,任何口罩都有它的区间。
结论2:任何一个口罩翻倍后,不舒适值必然大于原区间的所有口罩。

于是我们找了30个抽屉,将口罩放到对应抽屉里,标签贴上数量和不舒适值总和。
就可以每次拿一摞口罩,预先把不舒适值总和扣掉,全都用完再翻倍放入下个抽屉。
直到某个抽屉,我们剩余的不舒适值不足以拿走整个抽屉,那就把它们排个序挨个拿既可。

        // 1. 将数组排序,然后以2的幂为界分段求和、计数
        Arrays.sort(array);
        for (int i = 0, j = 1, x = 2; i < n && j < 31; i++) {
            while (array[i] >= x) {
                j++;
                x <<= 1;
            }
            sum[j] += array[i];
            count[j]++;
        }
        // 2. 将k依次减去每段的总和,按规则,将其翻倍后加到下一段,直到不够减
        int index = 0;
        while (k >= sum[++index]) {
            k -= sum[index];
            sum[index + 1] += sum[index] << 1;
            sum[index] = 0;
        }
        // 3. 遍历原数组,元素所属段的幂指数与最终幂指数的差就是翻倍的次数,顺便统计天数
        int days = 0;
        int offset = 0;
        for (int i = 1; i < index; i++) {
            for (int j = 0; j < count[i]; j++) {
                array[offset++] <<= index - i;
            }
            days += count[i] * (index - i);
        }
        // 4. 根据步骤2,最终结果在此区域,由于翻倍次数不同,重排序之后遍历
        Arrays.sort(array, 0, offset + count[index] - 1);
        for (int i = 0; i < array.length; i++) {
            k -= array[i];
            if (k < 0) {
                System.out.print(days + "\n");
                return;
            }
            days++;
        }


发表于 2025-12-19 11:31:51 回复(0)