小红拿到了一个数组,她可以进行最多两次操作:选择一个元素,使其加1。
小红希望操作结束后,数组所有元素乘积的二进制末尾有尽可能多的0。你能帮帮她吗?
第一行输入一个正整数,代表数组的大小。
第二行输入个正整数
,代表数组的元素。
输出一个整数,代表操作结束后,数组所有元素乘积的二进制末尾0的数量。
5 1 2 3 4 5
6
操作两次后数组变为 [2, 2, 4, 4, 5],数组乘积为 320,二进制表示为 101000000,有 6 个 0。
想要乘积的末尾的0最多,那就要数组中的数的2的因子要多,所以可以先求出原数组中的总共的2的因子的个数
然后去枚举每个元素,对同一个元素进行2次+1,然后求差值,
然后再去求出对原数组的2个元素,对这2个元素各加1带来的2的因子的增加,
然后求这2种情况的最大值
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void async function () {
let n = parseInt(await readline());
let arr = (await readline()).split(' ').map(Number);
// 使用位运算计算每个数中因子2的个数
function countFactorsOf2(num) {
if (num === 0) return 0;
let count = 0;
while ((num & 1) === 0) {
count++;
num >>= 1;
}
return count;
}
// 计算原始数组中因子2的总个数
let totalFactors = 0;
let gains = [];
for (let i = 0; i < n; i++) {
let original = countFactorsOf2(arr[i]);
let afterPlusOne = countFactorsOf2(arr[i] + 1);
totalFactors += original;
gains.push(afterPlusOne - original);
}
// 对增益进行排序
gains.sort((a, b) => b - a);
// 最多两次操作的最大增益
let maxGain = 0;
// 情况1: 两次操作作用于同一元素 (+2)
for (let i = 0; i < n; i++) {
let gainFromTwoOps = countFactorsOf2(arr[i] + 2) - countFactorsOf2(arr[i]);
maxGain = Math.max(maxGain, gainFromTwoOps);
}
// 情况2: 两次操作作用于不同元素 (各+1)
let gainFromTwoElements = Math.max(0, gains[0] || 0) + Math.max(0, gains[1] || 0);
maxGain = Math.max(maxGain, gainFromTwoElements);
console.log(totalFactors + maxGain);
}()