本蒟蒻的第一篇題解,如果有什麼不足,請dalao輕噴。。。
題意
題目傳送門
給出兩個數 \(n\) 和 \(m\),求出最小的整數 \(p\),使得 \(p\) \(\notin\) { \(n \oplus 1, n \oplus 2, n \oplus 3, ···, n \oplus m\) } 。
思路
異或
先思考這道題之前,還不如先思考這道題目所要用的符號 \(\oplus\) 有什麼性質。
其中,\(\oplus\) 的意思為:兩個數在二進位制狀態下,各個數位對齊,位數不夠就在前面補零,若兩個數位相同就得 \(1\),不同就得 \(0\)。
比如:$12 \oplus 5 = $,列個豎式
---\(1\) \(1\) \(0\) \(0\)
\(\oplus\) \(0\) \(1\) \(0\) \(1\)
\(=\) \(1\) \(0\) \(0\) \(1\)
\(=\) \(9\)
所以 \(12 \oplus 5 = 9\),我們再舉個例子:$12 \oplus 9 = $,不難得出答案為 \(5\)。
因此,我們發現異或的一個性質 \(a \oplus b = c\),也可以轉換為 \(a \oplus c = b\)。
解題
經過上面的推導,再看看題目,發現在程式中花括號中的資料可能會毫無規律,而且花括號中都有 \(n\),於是我們考慮將式子轉換為:\(n \oplus p\) \(\notin\) { \(1, 2, 3, ···,m\) }
所以題目就可以轉化為求一個最小的整數 \(p\),使得 $ n \oplus p > m $。
當然,如果列舉出 \(p\),時間肯定承受不了,所以只能構造出 \(p\)。
分類討論 :
- \(n_i = m_i = 0\),\(p_i = 0\),因為 \(p\) 要最小,如果 \(p_i = 1\),雖然也能滿足 \(n \oplus p > m\),但是 \(p\) 不是最小的。
- \(n_i = 0, m_i = 1\),\(p_i = 1\),同上。
- \(n_i = 1, m_i = 0\),\(p_i = 0\), 且後面全為零,因為這個數為已經大於 \(m_i\) 的這一位了,後面的不管再怎麼小也能滿足題目要求。
- \(n_i = m_i = 1\),\(p_i = 0\),同 \(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;
}