华为OD机试C卷 - 分苹果 - 二进制 - (Java C++ JavaScript Python)
一、题目描述
A、B两个人把苹果分为两堆。
A希望按照他的计算规则等分苹果,他的计算规则是按照二进制加法计算,并且不计算进位12+5=9(1100+0101=9);
B的计算规则是十进制加法,包括正常进位,B希望在满足A的情况下获取苹果重量最多。
输入苹果的数量和每个苹果重量,输出满足A的情况下B获取的苹果总重量。
如果无法满足A的要求,输出-1。
数据范围:
1<=总苹果数量<=20000
1<=每个苹果重量<=10000
二、输入描述
输入第一行是苹果数量:3
输入第二行是每个苹果重量:3 5 6
三、输出描述
输出第一行是B获取的苹果总重量:11
四、测试用例
用例1
输入
4
2 2 2 2
输出
6
说明
总苹果重量:2 + 2 + 2 + 2 = 8
二进制异或总和:2 ^ 2 ^ 2 ^ 2 = 0
最小苹果重量:2
B获取的苹果总重量:8 - 2 = 6
用例2
输入
3
1 2 3
输出
5
说明
总苹果重量:1 + 2 + 3 = 6
二进制异或总和:1 ^ 2 ^ 3 = 0
最小苹果重量:1
B获取的苹果总重量:6 - 1 = 5
五、解题思路
- A 的“不进位加法”即异或运算。
- 要使两堆异或值相等,必须满足:所有苹果的总异或为 0,否则无法划分 ⇒ 输出
-1
- 当总异或为 0 时,可以把任意一个苹果单独分给 A,其余给 B,都能满足 A 的条件
- 为了让 B 拿得最多,应让 A 拿最轻的那个苹果
- 因此 B 的最大重量为:总重量 - 最小苹果重量
六、Java源码实现
public static void main(String[] args) {Scanner sc = new Scanner(System.in);int count = sc.nextInt();// 异或和int aWeight = 0;// 十进制和int sumWeight = 0;// 最小重量int minWeight = Integer.MAX_VALUE;for (int i = 0; i < count; i++) {int weight = sc.nextInt();// 找到最小重量if (weight < minWeight) {minWeight = weight;}sumWeight += weight;aWeight ^= weight;}if (aWeight != 0) {System.out.println(-1);return;}// B要获取最大重量,就用总重量-最小重量System.out.println(sumWeight - minWeight);}
运行结果
七、C++源码实现
#include <iostream>
#include <climits> // 用于 INT_MAX
using namespace std;int main() {// 读取苹果的总数量int n;cin >> n;// 初始化变量long long sumWeight = 0; // 所有苹果的总重量(使用 long long 防止大数溢出)int xorSum = 0; // A 的“不进位加法”总和,即所有重量的异或结果int minWeight = INT_MAX; // 记录最轻的苹果重量,初始设为整型最大值// 循环读取每个苹果的重量for (int i = 0; i < n; ++i) {int weight;cin >> weight; // 输入当前苹果的重量// 累加到总重量(B 的十进制计算方式)sumWeight += weight;// 计算异或和(A 的不进位二进制加法)xorSum ^= weight;// 更新最小重量if (weight < minWeight) {minWeight = weight;}}// 判断是否能满足 A 的“等分”要求// A 要求两堆苹果的异或值相等// 数学推导:只有当所有苹果的总异或为 0 时,才可能分成两堆异或相等if (xorSum != 0) {// 无法满足 A 的条件,输出 -1cout << -1 << endl;} else {// 满足 A 的条件// 此时,可以把最轻的苹果单独分给 A,其余全给 B// 这样 B 拿到的重量最大,为:总重量 - 最小重量cout << (sumWeight - minWeight) << endl;}return 0; // 程序正常结束
}
八、JavaScript源码实现
function main() {const readline = require('readline');const rl = readline.createInterface({input: process.stdin,output: process.stdout});let lines = [];// 监听每行输入rl.on('line', (line) => {lines.push(line.trim());});// 输入结束时处理数据rl.on('close', () => {// 解析输入const n = parseInt(lines[0], 10); // 苹果数量const weights = lines[1].split(' ').map(Number); // 苹果重量数组// 初始化变量let sumWeight = 0; // 总重量(十进制和)let xorSum = 0; // 异或和(A 的不进位加法)let minWeight = Infinity; // 最小苹果重量// 遍历所有苹果for (let i = 0; i < n; i++) {const weight = weights[i];sumWeight += weight; // 累加总重量xorSum ^= weight; // 计算异或和if (weight < minWeight) {minWeight = weight; // 更新最小重量}}// 判断是否满足 A 的条件if (xorSum !== 0) {console.log(-1); // 无法等分} else {// B 能获得的最大重量:总重 - 最轻的一个console.log(sumWeight - minWeight);}});
}main();
九、Python源码实现
import sysdef main():"""主函数:解决 A 和 B 分苹果问题A 的规则:二进制不进位加法(即异或)B 的目标:在满足 A 的前提下,拿到最多的苹果重量"""# 读取苹果数量n = int(input().strip())# 读取每个苹果的重量weights = list(map(int, input().split()))# 初始化变量total_sum = 0 # 十进制总重量(B 的计算方式)xor_sum = 0 # 异或总和(A 的不进位加法)min_weight = float('inf') # 最小苹果重量,初始化为正无穷# 遍历每个苹果for weight in weights:total_sum += weight # 累加总重量xor_sum ^= weight # 计算异或和(A 的规则)if weight < min_weight:min_weight = weight # 更新最小重量# 判断是否能满足 A 的“等分”要求# 只有当所有苹果的异或和为 0 时,才能分成两堆使得 A 认为相等if xor_sum != 0:# 无法满足 A 的条件print(-1)else:# 满足 A 的条件# B 想让自己拿到的重量最多,应让 A 拿最轻的那个苹果# B 获得的最大重量 = 总重量 - 最小重量print(total_sum - min_weight)# 调用 main 函数启动程序
if __name__ == "__main__":main()