异或值
异或值
给定一个长度为 的整数序列 。
请你找到一个非负整数 ,使得 的值尽可能小,其中 表示按位异或。
输出 的最小可能值。
输入格式
第一行包含整数 。
第二行包含 个整数 。
输出格式
一个整数,表示 的最小可能值。
数据范围
前 个测试点满足 。
所有测试点满足 ,。
输入样例1:
3 1 2 3
输出样例1:
2
输入样例2:
2 1 5
输出样例2:
4
解题思路
先把每个数的二进制表示用Trie存下来,然后在Trie上dfs求异或结果的最小值。
从二进制的最高位(第位)开始看,的最高位有两种选择,即和。由于异或运算对每个位是独立的,我们可以先递归求出两棵子树(即和两个方向)在第位到第位中异或结果的最大值的最小值,假设存在且为(对应那个分支的子树)和(对应那个分支的子树)。如果的最高位是,那么异或结果的最大值的最小值就是。同理如果的最高位是,那么异或结果的最大值的最小值就是。最终的答案就是这两种情况的最小值,即。
更一般的,如果递归到的第位,那么第位到第位的异或结果的最大值的最小值就是
其中如果对应的那个分支不存在,那么令。如果对应的那个分支不存在,那么令。
然后是时间复杂度的问题,看上去好像每层递归都有两个分支,时间复杂度为。实则不然,因为Trie中最多只有个节点,因此时间复杂度应该是。
AC代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int N = 30e5 + 10; 5 6 int tr[N][2], idx; 7 8 void insert(int x) { 9 int p = 0; 10 for (int i = 29; i >= 0; i--) { 11 int t = x >> i & 1; 12 if (!tr[p][t]) tr[p][t] = ++idx; 13 p = tr[p][t]; 14 } 15 } 16 17 int dfs(int u, int d) { 18 if (d == -1) return 0; 19 int a = -2e9, b = -2e9; 20 if (tr[u][0]) a = dfs(tr[u][0], d - 1); 21 if (tr[u][1]) b = dfs(tr[u][1], d - 1); 22 return min(max(a, b + (1 << d)), max(a + (1 << d), b)); 23 } 24 25 int main() { 26 int n; 27 scanf("%d", &n); 28 while (n--) { 29 int x; 30 scanf("%d", &x); 31 insert(x); 32 } 33 printf("%d", dfs(0, 29)); 34 35 return 0; 36 }
参考资料
AcWing 4869. 异或值(AcWing杯 - 周赛):https://www.acwing.com/video/4644/
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/17181584.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2022-03-05 聪明的燕姿