本蒟蒻的第一篇题解,如果有什么不足,请dalao轻喷。。。
题意
给出两个数 n n n 和 m m m,求出最小的整数 p p p,使得 p p p ∉ \notin ∈/ { n ⊕ 1 , n ⊕ 2 , n ⊕ 3 , ⋅ ⋅ ⋅ , n ⊕ m n \oplus 1, n \oplus 2, n \oplus 3, ···, n \oplus m n⊕1,n⊕2,n⊕3,⋅⋅⋅,n⊕m } 。
思路
异或
先思考这道题之前,还不如先思考这道题目所要用的符号 ⊕ \oplus ⊕ 有什么性质。
其中, ⊕ \oplus ⊕ 的意思为:两个数在二进制状态下,各个数位对齐,位数不够就在前面补零,若两个数位相同就得 1 1 1,不同就得 0 0 0。
比如:$12 \oplus 5 = $,列个竖式
— 1 1 1 1 1 1 0 0 0 0 0 0
⊕ \oplus ⊕ 0 0 0 1 1 1 0 0 0 1 1 1
= = = 1 1 1 0 0 0 0 0 0 1 1 1
= = = 9 9 9
所以 12 ⊕ 5 = 9 12 \oplus 5 = 9 12⊕5=9,我们再举个例子:$12 \oplus 9 = $,不难得出答案为 5 5 5。
因此,我们发现异或的一个性质 a ⊕ b = c a \oplus b = c a⊕b=c,也可以转换为 a ⊕ c = b a \oplus c = b a⊕c=b。
解题
经过上面的推导,再看看题目,发现在程序中花括号中的数据可能会毫无规律,而且花括号中都有 n n n,于是我们考虑将式子转换为: n ⊕ p n \oplus p n⊕p ∉ \notin ∈/ { 1 , 2 , 3 , ⋅ ⋅ ⋅ , m 1, 2, 3, ···,m 1,2,3,⋅⋅⋅,m }
所以题目就可以转化为求一个最小的整数 p p p,使得 $ n \oplus p > m $。
当然,如果枚举出 p p p,时间肯定承受不了,所以只能构造出 p p p。
分类讨论 :
- n i = m i = 0 n_i = m_i = 0 ni=mi=0, p i = 0 p_i = 0 pi=0,因为 p p p 要最小,如果 p i = 1 p_i = 1 pi=1,虽然也能满足 n ⊕ p > m n \oplus p > m n⊕p>m,但是 p p p 不是最小的。
- n i = 0 , m i = 1 n_i = 0, m_i = 1 ni=0,mi=1, p i = 1 p_i = 1 pi=1,同上。
- n i = 1 , m i = 0 n_i = 1, m_i = 0 ni=1,mi=0, p i = 0 p_i = 0 pi=0, 且后面全为零,因为这个数为已经大于 m i m_i mi 的这一位了,后面的不管再怎么小也能满足题目要求。
- n i = m i = 1 n_i = m_i = 1 ni=mi=1, p i = 0 p_i = 0 pi=0,同 1 1 1。
Code
#include <cstdio>
#include <iostream>
using namespace std;
int n, m;
void Main() {
cin >> n >> m;
m++;
int p = 0;
for (int i = 30; i >= 0; i--) {
if (((1 & (n >> i)) == 0) && ((1 & (m >> i)) == 1)) p = (1 << i) | p;
if (((1 & (n >> i)) == 1) && ((1 & (m >> i)) == 0)) break;
}
cout << p << endl;
}
int main() {
int T;
for (cin >> T; T; T--) Main();
return 0;
}