题目链接
塔子哥的编程乐趣-腾讯2023笔试(codefun2000)
题目内容
塔子哥是一位资深的程序员,他最近在研究一种特殊的数组操作。他有一个由正整数组成的数组,数组的长度是偶数。塔子哥可以对数组中的任意一个数字执行以下两种操作之一:将该数字乘以 2;将该数字除以 2 并向下取整。
塔子哥的目标是通过一系列操作,使得最终数组中恰好一半的数字是奇数,另一半是偶数。他希望找到一种方案,使得操作次数最少。
输入描述
输入的第一行包含一个正偶整数 n,表示数组的长度。
第二行包含 n 个正整数 A1 ,A2 ,…,An,表示初始的数组。
输出描述
输出一个整数,表示达成目标所需的最少操作次数。
样例1
输入
6
1 1 4 5 1 4
输出
1
样例2
输入
8
1 2 4 5 6 10 8 8
输出
2
提示
初始数组为 [1,1,4,5,1,4]。将第四个数字 5 除以 2 并向下取整,得到 [1,1,4,2,1,4],此时数组中恰好一半是奇数,另一半是偶数。
评测数据与规模对于所有评测用例,满足 2 ≤ n ≤ 1 0 5 , 1 ≤ A i ≤ 1 0 9 2≤n≤10^5 ,1≤Ai ≤10^9 2≤n≤105,1≤Ai≤109 ,并且 n 是偶数。
题解1
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n, cnt0, cnt1, st[N]; // st[i]表示将第i个偶数转成奇数的最少操作次数
int main(){
scanf("%d", &n);
for(int i = 1, x; i <= n; i++){
scanf("%d", &x);
if(x&1) cnt1++; // 奇数个数+1
else{
cnt0++; // 偶数个数+1
for(int j = 31; j>=1; j--){
// (x)&(-x)得到的是一个数的二进制表示的末尾1的对应值
// 比如:x=6,则的x的二进制表示为110,则(x)&(-x)=(110)&(010)= 010
// -6的二进制表示是对110先按位取反得到001,再加1得到010,即110 -> 001 -> 010
if(1<<j == (x&(-x))){
st[cnt0] = j;
break;
}
}
}
}
long long ans = 0;
if(cnt0 == cnt1){ // 奇数个数和偶数个数一样多
ans = 0;
} else if(cnt0 < cnt1){ // 奇数个数多于偶数个数,只需要进行这样的操作:一个奇数乘以2,就可以得到偶数;重复这样的操作,直到奇数个数和偶数个数一样多
ans = (cnt1 - cnt0)/2;
}else { // 奇数个数少于偶数个数,需要将若干偶数转成奇数;需要得到每个偶数转成奇数的最少操作数,然后按最少操作数进行升序排序,选择最小的若干个,直到奇数个数和偶数个数一样多
sort(st+1, st+1+cnt0);
int num = (cnt0 - cnt1)/2; // num表示需要将偶数转变成奇数的个数
for(int i = 1; i <= num; i++){
ans += st[i];
}
}
printf("%lld\n", ans);
return 0;
}
标签:塔子哥,奇数,int,cnt0,个数,偶数,数组,2023,codefun2000
From: https://blog.csdn.net/qq_45332149/article/details/140819722