一、题目描述
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源码实现
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++源码实现
cpp
#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 的条件,输出 -1
cout << -1 << endl;
} else {
// 满足 A 的条件
// 此时,可以把最轻的苹果单独分给 A,其余全给 B
// 这样 B 拿到的重量最大,为:总重量 - 最小重量
cout << (sumWeight - minWeight) << endl;
}
return 0; // 程序正常结束
}
八、JavaScript源码实现
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源码实现
python
import sys
def 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()