C. Bitwise Balancing
题意
给定三个非负整数 b、c 和 d 。
请找到一个非负整数 a ∈ [ 0 , 2 61 ] a \in [0, 2^{61}] a∈[0,261] 使得 ( a ∣ b ) − ( a & c ) = d (a\, |\, b)-(a\, \&\, c)=d (a∣b)−(a&c)=d ,其中 ∣ | ∣ 和 & \& & 分别表示按位或运算和按位与运算。
如果存在这样的 a a a ,请输出它的值。如果没有解,请输出整数 − 1 -1 −1 。如果存在多个解,输出其中任意一个。
一、问题分析
注意问题中说的是输出任意一个,也就是说问题的合法答案有多个。
上图为 b,c,d 的真值表。
可以观察到 b,c,d 为 1,0,0 或 0,1,1 时是不可能的; 没有合法的 a,因此此时输出答案 -1。
二、代码
代码如下:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
void solve() {
ll a = 0, b, c, d, pos = 1, bit_b, bit_c, bit_d, mask = 1;
cin >> b >> c >> d;
for (ll i = 0; i < 62; i++) {
// 确定b,c,d的每一位
if (b&mask) bit_b = 1;
else bit_b = 0;
if (c&mask) bit_c = 1;
else bit_c = 0;
if (d&mask) bit_d = 1;
else bit_d = 0;
// 不合法情况,一种是b=1,c=0,d=0,另一种是b=0,c=1,d=1
if ((bit_b && (!bit_c) && (!bit_d)) || ((!bit_b) && bit_c && bit_d)) {
pos = 0;
break;
}
// 合法情况
if (bit_b && bit_c) {
// b=1,c=1,d=0/1 --> a=1/0
a += (1ll-bit_d)*mask;
} else {
// 其它的找到其中一种合法情况即可
/**
* b=0,c=0,d=0 --> a=0
* b=0,c=0,d=1 --> a=1
* b=0,c=1,d=0 --> a=1/0
* b=0,c=1,d=1 --> a=1/0
* 对于b=0,c=1,d=0和b=0,c=1,d=1,a=1/0,只要找到一个合法情况即可
*/
a += bit_d*mask;
}
// 位移 mask, 用于构建 a 下一位
mask<<=1;
}
// 通过pos判断是否合法
if (pos) {
cout << a << "\n";
} else {
cout << -1 << "\n";
}
}
int main() {
ll t;
cin >> t;
while (t--) {
solve();
}
}
其中代码
// 合法情况
if (bit_b && bit_c) {
// b=1,c=1,d=0/1 --> a=1/0
a += (1ll-bit_d)*mask;
} else {
// 其它的找到其中一种合法情况即可
/**
* b=0,c=0,d=0 --> a=0
* b=0,c=0,d=1 --> a=1
* b=0,c=1,d=0 --> a=1/0
* b=0,c=1,d=1 --> a=1/0
* 对于b=0,c=1,d=0和b=0,c=1,d=1,a=1/0,只要找到一个合法情况即可
*/
a += bit_d*mask;
}
根据真值表也可以变成
// 合法情况
if (!bit_b && !bit_c) {
// b=1,c=1,d=0/1 --> a=0/1
a += bit_d*mask;
} else {
// 其它的找到其中一种合法情况即可
/**
* b=1,c=1,d=0 --> a=1
* b=1,c=1,d=1 --> a=0
* b=0,c=1,d=0 --> a=1/0
* b=0,c=1,d=1 --> a=1/0
* 对于b=0,c=1,d=0和b=0,c=1,d=1,a=1/0,只要找到一个合法情况即可
*/
a += (1ll-bit_d)*mask;
}
之后按位构建 a 即可找到一个合法答案。
总结
本题构建真值表,之后发现不合法情况,按位构建 a 的思路值得学习。