A25135. 取糖果
题目描述
取糖果
题目描述:
圣诞节时,乐乐进入了一个神奇的糖果屋,糖果屋中有 n 个罐子,每个罐子中都有若干颗糖果。糖果屋的主人为了欢迎远道而来的乐乐,让乐乐感受到糖果屋的甜蜜,允许乐乐拿取 k 次糖果,拿取规则如下:
1)每次可以从任意一个罐子中拿取一颗糖果;
2)每次拿取糖果时能够获得甜蜜值,获得的甜蜜值为拿取前这个罐子中糖果的数量。
现给定两个整数 n 和 k,以及 n 个罐子中糖果的数量。已知乐乐初始的甜蜜值为 0,请计算按照规则他能够获得的最大甜蜜值。
例如:n = 3,k = 4,3 个罐子中糖果数量依次为 10,5,11,能够获得最大甜蜜值的拿取方式如下:
第一次拿取第 3 个罐子中的一颗糖果,获得的甜蜜值为 11,拿取后 3 个罐子中糖果数量依次为 10,5,10;
第二次拿取第 1 个罐子中的一颗糖果,获得的甜蜜值为 10,拿取后 3 个罐子中糖果数量依次为 9,5,10;
第三次拿取第 3 个罐子中的一颗糖果,获得的甜蜜值为 10,拿取后 3 个罐子中糖果数量依次为 9,5,9;
第四次拿取第 1 个罐子中的一颗糖果,获得的甜蜜值为 9,拿取后 3 个罐子中糖果数量依次为 8,5,9;
最终获得的最大甜蜜值为 40(11 + 10 + 10 + 9)。
输入描述:
第一行输入两个正整数 n,k(1≤n≤105,1≤k≤109),分别表示糖果屋中罐子的数量以及乐乐可以拿取糖果的次数;
第二行输入 n 个整数(1≤整数≤109),表示每个罐子中糖果的数量,整数之间以一个空格隔开。
数据保证,所有罐子的糖果总数大于 k。
输出描述:
输出一个正整数,表示乐乐能够获得的最大甜蜜值。
样例输入:
3 4
10 5 11样例输出:
40参考答案
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long LL;
int main() {
LL n, k, total_sum = 0;
cin >> n >> k;
vector<LL> a(n);
for (int i = 0; i < n; i++) cin >> a[i];
sort(a.begin(), a.end(), greater<LL>());
LL width = 1, current_level = a[0], rem = k;
int index = 0;
while (rem > 0 && current_level > 0) {
LL next_level = (index < n-1) ? a[index+1] : 0;
LL thickness = current_level - next_level;
if (rem >= width * thickness) {
total_sum += width * (current_level + next_level + 1) * thickness / 2;
rem -= width * thickness;
current_level = next_level;
if (++index < n) width = index + 1;
} else {
LL full = rem / width;
LL extra = rem % width;
total_sum += width * (current_level + current_level - full + 1) * full / 2;
total_sum += extra * (current_level - full);
rem = 0;
}
}
cout << total_sum << endl;
return 0;
}答案解析
贪心策略按糖果数分层计算:
排序:糖果数降序排列。
分层处理:计算每层厚度(与下一层差值),整层拿取时用等差数列求和。
剩余处理:部分层时用整数除法分离完整层和余数。
更新状态:进入下一层并更新罐子数和层宽。