CF2153B Bitwise Reversion | 数学 | 模拟
题目描述
给定三个非负整数 \(x\),\(y\) 和 \(z\),判断是否存在三个非负整数 \(a\)、\(b\)、\(c\),满足以下三个条件:
- \(a \mathbin{\&} b = x\)
- \(b \mathbin{\&} c = y\)
- \(a \mathbin{\&} c = z\)
其中 \(\mathbin{\&}\) 表示按位与运算。
数据范围
输入包含多组测试数据。第一行包含一个整数 \(t\)(\(1 \leq t \leq 10^4\)),表示测试数据的组数。
接下来每组测试数据占一行,每行包含三个整数 \(x\)、\(y\) 和 \(z\)(\(0 \leq x, y, z \leq 10^9\)),分别表示 \(a \mathbin{\&} b\)、\(b \mathbin{\&} c\) 和 \(a \mathbin{\&} c\) 的目标值。
5
1 1 1
3 2 6
4 8 12
9 10 12
12730 3088 28130
YES
YES
NO
YES
NO
题解及证明过程
我们知道 \(x_i,y_i,z_i \in \left\{ 0,1\right\}\) 且 \(a_i,b_i,c_i \in \left\{ 0,1\right\}\),为了找出满足 \(a \mathbin{\&} b = x\),\(b \mathbin{\&} c = y\),\(a \mathbin{\&} c = z\) 的数,我们尝试通过排列组合所有情况。
可知对于一组 \((a_i,b_i,c_i)\) 有 \(8\) 种情况。排列组合后后算出对应的 \(x_i,y_i,z_i\) 的值即可。如下:
| \(a_i\) | \(b_i\) | \(c_i\) | \(x_i\) | \(y_i\) | \(z_i\) |
|---|---|---|---|---|---|
| \(0\) | \(0\) | \(0\) | \(0\) | \(0\) | \(0\) |
| \(1\) | \(0\) | \(0\) | \(0\) | \(0\) | \(0\) |
| \(0\) | \(1\) | \(0\) | \(0\) | \(0\) | \(0\) |
| \(0\) | \(0\) | \(1\) | \(0\) | \(0\) | \(0\) |
| \(1\) | \(1\) | \(0\) | \(1\) | \(0\) | \(0\) |
| \(0\) | \(1\) | \(1\) | \(0\) | \(1\) | \(0\) |
| \(1\) | \(0\) | \(1\) | \(0\) | \(0\) | \(1\) |
| \({\color{Red} 1}\) | \({\color{Red} 1}\) | \({\color{Red} 1}\) | \({\color{Red} 1}\) | \({\color{Red} 1}\) | \({\color{Red} 1}\) |
由表可知,如果 \(x_i=1\),\(y_i=1\),则一定有 \(z_i=1\)。如果 \(x_i=1\),\(z_i=1\),则一定有 \(y_i=1\)。如果 \(y_i=1\),\(z_i=1\),则一定有 \(x_i=1\)。
我们同样可以用本文中的要求来证明。根据 \(a \mathbin{\&} b = x\),\(b \mathbin{\&} c = y\),\(a \mathbin{\&} c = z\),所以当 \(x_i=1\),\(y_i=1\) 时,\(a_i=b_i=1\) 且 \(b_i=c_i=1\),所以 \(a_i=c_i=1\),此时代入 \(a \mathbin{\&} c = z\),则 \(z_i=a_i \mathbin{\&} c_i =1\mathbin{\&} 1=1\),故定理成立。同理可证明其他两个结论。
因为 \(0 \leq x, y, z \leq 10^9\),所以我们直接遍历前 \(30\)(因为 \(\log_2 (10^9)\approx 30\))个二进制位。使用布尔形型变量检查其是否满足标准即可。注意数组下标从 \(0\) 开始。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll T,x,y,z;
int main(){cin>>T;while(T--){cin>>x>>y>>z;bool f=1;for(int i=0;i<31;i++){ll x2=(x>>i)&1,y2=(y>>i)&1,z2=(z>>i)&1;if(x2&y2&&!z2){f=0; break;}if(x2&z2&&!y2){f=0; break;}if(y2&z2&&!x2){f=0; break;}}if(f) cout<<"Yes\n";else cout<<"No\n";}return 0;
}