[Codeforces Round #613 (Div. 2)] - D
Problem
Solution
这个题目的一种解法 ———— Tire上树形dp。 (第一次听说这种做法) 相信听到这个做法后,你大概就知道怎么做了。
首先先把所有数字建成一棵 Tire,根节点的儿子表示第 30 位,然后依次类推(从高位往低位建)。
假设点 u 的儿子表示的是第 k 位,那么点 u 的儿子的意义就是:左儿子这边的数第 k 位上是 1,反之,右儿子这边的数第 k 位上是 0。
如果点 u 只有一个儿子,那么我们需要构造的数 x 的第 k 位就选这个儿子代表的数 (0/1),因为这样异或后就可以抵消。
如果点 u 有两个儿子,那么我们需要构造的数 x 的第 k 位选什么都会有 (1<<k) 的影响,这时我们要使总答案最小就要取 min{ls(),rs()}
实际做的时候并不要把树建出来。
Code
Talk is cheap.Show me the code.
#include<bits/stdc++.h>
using namespace std;
inline int read() {
int x=0,f=1; char ch=getchar();
while(ch<'0' || ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
while(ch>='0'&&ch<='9') { x=(x<<3)+(x<<1)+(ch^48); ch=getchar(); }
return x * f;
}
int n;
vector<int> a;
int Solve(vector<int> p,int K) {
if(p.size()==0 || K<0) return 0;
vector<int> p1,p2;
for(int i=0;i<p.size();++i) {
if(p[i] & (1<<K)) p1.push_back(p[i]);
else p2.push_back(p[i]);
}
if(p1.size() == 0) return Solve(p2,K-1);
else if(p2.size() == 0) return Solve(p1,K-1);
else return (1<<K) + min(Solve(p1,K-1),Solve(p2,K-1));
}
int main()
{
n = read();
for(int i=1,x;i<=n;++i) {
x = read();
a.push_back(x);
}
printf("%d\n",Solve(a,30));
return 0;
}
Summary
Trie上树形dp,经典题。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步