众所周知,戴口罩是很不舒服的。小红每个口罩戴一天的初始不舒适度为
小红有时候会将口罩重复使用(注:这是非常不卫生的!),每次重复使用时,该口罩的不舒适度会翻倍!
小红想知道,自己在不舒适度总和不超过
第一行输入两个正整数和
,分别代表口罩的总数、以及小红最多能忍受的不舒适度总和。
第二行输入个正整数
,用空格隔开。分别代表每个口罩初始的不舒适度。
一个整数,代表小红最多能度过的天数。
2 30 2 3
5
第一天用第一个口罩,不舒适度为2。
第二天用第一个口罩,不舒适度为4。
第三天用第二个口罩,不舒适度为3。
第四天用第二个口罩,不舒适度为6。
第五天用第二个口罩,不舒适度为12。
总不舒适度为2+4+3+6+12=27,没有超过30。
可以证明,无论怎样分配,都无法度过6天且不舒适度总和不超过30
3 5 7 6 8
0
显然,使用任何一个口罩都会使不舒适度超过5。
// 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++;
}