除2!

98 篇文章 1 订阅
89 篇文章 0 订阅

除2! ⁡ \operatorname{除2!} 2

题目链接: nowcoder 213140 ⁡ \operatorname{nowcoder\ 213140} nowcoder 213140

到牛客看:

——>点我跳转<——

题目

给一个数组,一共有 n n n 个数。
你能进行最多 k k k 次操作。每次操作可以进行以下步骤:
选择数组中的一个偶数 a i a_i ai,将其变成 a i / 2 a_i/2 ai/2
现在你进行不超过 k k k 次操作后,让数组中所有数之和尽可能小。请输出这个最小的和。

输入

第一行输入两个正整数 n n n k k k,用空格隔开
第二行输入 n n n 个正整数 a i a_i ai

输出

一个正整数,代表和的最小值。

样例输入

5 3
2 4 8 10 11

样例输出

24

样例解释

8 8 8 操作 2 2 2 次,对 10 10 10 操作 1 1 1 次,最后的数组是 2   4   2   5   11 2\ 4\ 2\ 5\ 11 2 4 2 5 11。可以证明这样的操作是最优的。

数据范围

1 ≤ n ≤ 100000 , 1 ≤ k ≤ 1 0 9 1 ≤ n≤100000,1≤k≤10^9 1n1000001k109
1 ≤ a i ≤ 1 0 9 1≤a_i≤10^9 1ai109

思路

一道小贪心。

我们很明显可以看出,我们要进行操作是总和变得更小,肯定每一次就是贪心选择最大的偶数进行操作。
(因为这样总和减去的值就会大)

我就直接弄个了堆,把所有偶数丢进去,奇数就直接算进答案里面。
然后每次把最大的拿出来 / 2 /2 /2,如果变成了奇数,就直接算进答案里面,否则就重新把除了之后的数塞进去。

然后最后把堆里的数加进答案,就可以了。

然后如果堆空了(就是所有数都变成了奇数),那就直接退出,不用枚举 k k k 次那么多。

代码

#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;
} 
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值