題目鏈接:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1216
題目大意是給了n個數,然后取出兩個數,使得xor值最大。
首先暴力枚舉是C(n, 2),顯然不行。
考慮每一個數,顯然,從最高位開始,如果它能和某一個數xor,讓最高位為1,效果肯定是最佳的。其次考慮次高位,以此類推。
簡單說,就是x的某一位,如果能找到某些數與x這一位xor為1,則考慮這些數,然后比較下一位;否則,就直接考慮下一位。起始從最高位開始考慮。
在這種貪心策略下,用字典樹保存搜索每一位的效率比較高。
需要注意的是,由於是xor運算,所以需要保證每一個數的位數一樣長,因為是32位有符號的int型,於是統一成31位長。
還有就是,理論上需要先把所有數,存入字典樹,然后討論每一個數,但是對於一個x,如果它能和y這個數xor出最大值,那么不管是先存入了x,還是先存入了y,(x, y)這個數對是肯定會被討論的。所以,完全可以存入一個數,就討論一個數。
代碼:

#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <algorithm> #include <set> #include <map> #include <queue> #include <string> #define LL long long using namespace std; const int maxN = 100005; const int len = 31;//len表示數的二進制最大長度 struct Trie { int next[2]; }tree[maxN*len]; int cnt, ans, n; void initTree() { cnt = 0; memset(tree, -1, sizeof(tree)); } void add(int x) { int now = 0; bool k; for (int i = len; i >= 0; i--) { k = x&(1<<i); if (tree[now].next[k] == -1) tree[now].next[k] = ++cnt; now = tree[now].next[k]; } } //返回當前數中能和x合成最大數的數 int query(int x) { int v = 0, now = 0; bool k; for (int i = len; i >= 0; i--) { k = x&(1<<i); if (tree[now].next[!k] != -1) k = !k; v = v|(k<<i); now = tree[now].next[k]; } return v; } void work() { ans = 0; initTree(); int x; for (int i = 0; i < n; ++i) { scanf("%d", &x); add(x); ans = max(ans, x^query(x)); } printf("%d\n", ans); } int main() { //freopen("test.in", "r", stdin); while (scanf("%d", &n) != EOF) { work(); } return 0; }