链接:https://ac.nowcoder.com/acm/contest/8563/A

来源:牛客网

题目描述

给一个数组,一共有n个数。
你能进行最多k次操作。每次操作可以进行以下步骤:

选择数组中的一个偶数ai,将其变成 ai/2 。

现在你进行不超过k次操作后,让数组中所有数之和尽可能小。请输出这个最小的和。

输入描述:

第一行输入两个正整数nk,用空格隔开 

第二行输入n个正整数ai

数据范围:

1≤n≤100000,1≤k≤109

1≤ai≤10^9

输出描述:

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

示例1

输入

5 3

2 4 8 10 11

输出

24

思路:先求和,将偶数都加入优先队列,每次取最大的偶数除以2,如果还是偶数就将它继续加入优先队列。维护最大偶数,当没有偶数或已操作m次时退出循环,此时和最小。

AC代码

 

#include<bits/stdc++.h>
using namespace std;
inline char getc(){
    static char buf[1000000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
int sca()
{
    int su=0,f=1;char c=getchar();
    while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    while(isdigit(c))su=su*10+c-'0',c=getchar();
    return su*f;
}
int main()
{
    int n,m,x;
    n=sca();m=sca();
    priority_queue<int>p;
    long long su=0;
    for(int i=1;i<=n;++i)
        {
            x=sca();
            if(x%2==0)
                p.push(x);
            su+=x;
        }
    while(!p.empty()&&m--)
    {
        int te=p.top()/2;
        p.pop();
        if(te%2==0)//将偶数加入优先队列,维护最大的偶数
            p.push(te);
        su-=te;//每次减少偶数的一半
    }
    printf("%lld\n",su);
}