21.5.12 t1
阿新 • • 發佈:2021-06-25
今回是Jill鎮樓,
今天題目還是感覺很有意思的,我推薦大家都做,做對了就做爽了(
題幹:
在給定的NN個整數A1,A2……ANA1,A2……AN中選出兩個進行xorxor(異或)運算,得到的結果最大是多少?
輸入格式
第一行輸入一個整數NN。
第二行輸入NN個整數A1A1~ANAN。
輸出格式
輸出一個整數表示答案。
資料範圍
1≤N≤1051≤N≤105,
0≤Ai<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; }