题目链接:https://ac.nowcoder.com/acm/problem/213140
到主站看:https://blog.csdn.net/weixin_43346722/article/details/109688868
题目
给一个数组,一共有 个数。
你能进行最多 次操作。每次操作可以进行以下步骤:
选择数组中的一个偶数 ,将其变成
。
现在你进行不超过 次操作后,让数组中所有数之和尽可能小。请输出这个最小的和。
输入
第一行输入两个正整数 和
,用空格隔开
第二行输入 个正整数
输出
一个正整数,代表和的最小值。
样例输入
5 3 2 4 8 10 11
样例输出
24
样例解释
对 操作
次,对
操作
次,最后的数组是
。可以证明这样的操作是最优的。
数据范围
思路
一道小贪心。
我们很明显可以看出,我们要进行操作是总和变得更小,肯定每一次就是贪心选择最大的偶数进行操作。
(因为这样总和减去的值就会大)
我就直接弄个了堆,把所有偶数丢进去,奇数就直接算进答案里面。
然后每次把最大的拿出来 ,如果变成了奇数,就直接算进答案里面,否则就重新把除了之后的数塞进去。
然后最后把堆里的数加进答案,就可以了。
然后如果堆空了(就是所有数都变成了奇数),那就直接退出,不用枚举 次那么多。
代码
#include<queue> #include<cstdio> #include<algorithm> using namespace std; priority_queue <int> a; int n, k, x; long long ans; int main() { scanf("%d %d", &n, &k); for (int i = 1; i <= n; i++) { scanf("%d", &x); if (x & 1) ans += (long long)x; else a.push(x); } while (k && !a.empty()) { x = a.top(); a.pop(); x /= 2; if (x & 1) ans += (long long)x; else a.push(x); k--; } while (!a.empty()) ans += (long long)a.top(), a.pop(); printf("%lld", ans); return 0; }