原題連接ios
在給定的N個整數A1,A2……AN中選出兩個進行xor(異或)運算,獲得的結果最大是多少?函數
輸入格式
第一行輸入一個整數N。spa
第二行輸入N個整數A1~AN。code
輸出格式
輸出一個整數表示答案。ci
數據範圍
1 ≤ N ≤ 10^5,
0 ≤ Ai < 2^31get
輸入樣例:io
3 1 2 3
輸出樣例:stream
3
解題關鍵:循環
由於異或時只有當兩個數相同二進制數位上的數字不一樣時纔會爲 1,1 ^ 0 = 1
, 0 ^ 1 = 1
, 0 ^ 0 = 0
, 1 ^ 1 = 0
,因此要找出最大的異或對,就須要讓兩個數的二進制數位上的數儘量不一樣便可。二進制
Q & A :
Q :這裏對於 ~i
作一下解釋,爲何 ~i
能夠等價於i >= 0
?
A :-1 在二進制中全是 1,因此 -1 的反碼的二進制就全是 0 了,這樣當 i--
一直減,減到 -1 的時候就能跳出循環了。(🤪其實並無什麼卵用,就只是在關鍵時候影響一下代碼的可讀性而已)。
最後,解釋一下代碼中的Query()
函數中的 res += 1 << i;
的意思。此處截取Y總的解釋:若是當前子樹中,存在第 i 位和 x 的第 i 位不一樣的數,說明答案的第 i 位能夠變成 1,就把 res 的第 i 位二進制位變成 1 。
完整AC代碼:
#include <iostream> #include <cstdio> using namespace std; const int N = 100010, M = 3100010; int son[M][2], idx; void Insert(int x){ int p = 0; for(int i = 30; ~i; i--){ //~i等價於i >= 0,這裏從x二進制的第31位開始枚舉每一位上的數,因此這裏左移了30位,枚舉的是第31位上的數 int u = x >> i & 1; //判斷x這個數的第i位上的數是1仍是0 if(!son[p][u]) son[p][u] = ++ idx; p = son[p][u]; } } int Query(int x){ int p = 0, res = 0; for(int i = 30; ~i; i--){ int u = x >> i & 1; //若是u == 1說明第i爲上的數爲1,若是爲0則反之。 if(son[p][!u]){ //判斷和x這個數的第i位上不同的數的這個分支是否是存在的。 //若是存在,說明異或出來的這個數的第i位上的數能夠爲1 res += 1 << i; p = son[p][!u]; } //和x這個數的第i位上不同的數的這個分支不存在 else p = son[p][u]; //不存在就只能讓p走向存在的這個分支 } return res; } int main(){ int n, res = 0; cin >> n; //讀入數據 for(int i = 0; i < n; i++){ int x; cin >> x; Insert(x); res = max(res, Query(x)); } cout << res << endl; return 0; }