1. 程式人生 > 其它 >21.5.12 t1

21.5.12 t1

今回是Jill鎮樓,

今天題目還是感覺很有意思的,我推薦大家都做,做對了就做爽了(

題幹:

在給定的NN個整數A1A2ANA1,A2……AN中選出兩個進行xorxor(異或)運算,得到的結果最大是多少?

輸入格式

第一行輸入一個整數NN。

第二行輸入NN個整數A1A1~ANAN。

輸出格式

輸出一個整數表示答案。

資料範圍

1N1051≤N≤105,
0Ai<2310≤Ai<231

輸入樣例:

3
1 2 3

輸出樣例:

3

暴力我們就不解釋了,一個個對比是O(n^2),複雜度爆了。

我們看題目要求異或值,自然會想到二進位制。

假設我們有一個圖,圖上有所有給出數的二進位制表示,

我們如何給出關於一個數的最大異或值?

我們只要找每一個對應二進位制位數儘量相反(位數從高到低選取),就能保證有最大異或值。

如果我們找n個數的任意兩個數最大的異或值,最壞只有O(n*32);

自然會想到只有零一的左右兒子的二叉樹,我們一建樹,一看題目,空間爆了(

我們然後就會想到用字典數的建樹方法來建這個只有零一的二叉樹。

結果,程式碼如下啦:

#include<cstdio>
#include<cmath>
#include<cstring>
const int maxn = 1e5 + 10;
int bit[33 * maxn][2], n, k, a[maxn], t[35
]; inline int max(int a, int b) {return a > b ? a : b;} void into(int x) { int p = 1,pos=0,i=0,tp=x; memset(t, 0, sizeof t); while (x) { t[p] = x % 2; x = x / 2; ++p; } for (i = 32; i; --i) { if(!bit[pos][t[i]]) bit[pos][t[i]] = ++k; pos
= bit[pos][t[i]]; } } int find(int x) { int pos = 0, maxx = 0, ans[35] = { 0 }, p = 1, v = 0; memset(t, 0, sizeof t); while (x) { t[p] = x % 2; x = x / 2; ++p; } for (int i = 32; i; --i) { if (bit[pos][!t[i]])ans[i] = 1, v = !t[i]; else ans[i] = 0, v = t[i]; pos = bit[pos][v]; } for (int i = 32; i; --i) maxx += ans[i] * pow(2, i - 1); return maxx; } int main() { int ans = 0; freopen("C:\\Users\\Towetrlone\\Desktop\\qwq.txt", "r", stdin); scanf("%d", &n); for (int i = 1; i <= n; ++i) scanf("%d", &a[i]),into(a[i]); for (int i = 1; i <= n; ++i) ans = max(ans, find(a[i])); printf("%d", ans); return 0; }