可以选俩一样的数,但自己异或自己结果是0,不是最优解
预备知识,啥是异或
暴力做法就是两层for循环枚举所有可能
暴力的思路就是
1:首先选定一个Ai(1 <= i <= n)
2:在A1 ~ An中选择一个数Aj,使得Ai ^ Aj的值最大
突破点在第2步
首先Ai一定小于等于31位,也就是0 <= Ai <= 2 ^ 31 - 1
本题思路:
首先对所有的Ai,根据每一位的0和1,建立一个Trie树
然后对于每一个固定的Ai的话
在Trie树中寻找,从根节点往下走
每次尽量往和Ai这一位上的数字不同的数字这一个分支上走,这样才能使得两个数异或出来的值最大
模拟样例
时间复杂度10 ^ 5 * 31
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 100010, M = 4e6 + 10; 4 //M是Trie的总节点个数 = 10 ^ 5 * 31 5 int a[N], son[M][2], idx; 6 void insert(int x) { 7 int p = 0; 8 for (int i = 30; i >= 0; i--) { 9 int &s = son[p][x >> i & 1]; 10 if (!s) { 11 s = ++ idx; //创建新结点 12 } 13 p = s; 14 } 15 } 16 int query(int x) { //找到和x异或值最大的结果 17 int p = 0; 18 int res = 0; 19 for (int i = 30; i >= 0; i--) { 20 int s = x >> i & 1; 21 if (son[p][!s]) { 22 res += 1 << i; 23 p = son[p][!s]; 24 } else { 25 p = son[p][s]; 26 } 27 } 28 return res; 29 } 30 int main() { 31 int n; 32 cin >> n; 33 for (int i = 0; i < n; i++) { 34 cin >> a[i]; 35 insert(a[i]); 36 } 37 int res = 0; 38 for (int i = 0; i < n; i++) { 39 res = max(res, query(a[i])); 40 } 41 cout << res << endl; 42 return 0; 43 }