CF1554C Mikasa

wuzihenb發表於2024-08-27

本蒟蒻的第一篇題解,如果有什麼不足,請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;
}