F - Xor Minimization Editorial by en_translator
If the \(2^{29}\)’s place in the binary notation of an integer is \(1\), the integer is greater than any integer whose \(2^{29}\)’s place is \(0\) (regardless of \(2^{28}\)’s place, \(2^{27}\)’s place, and so on). Therefore, we come up with a greedy algorithm where we consider the following problem for each \(i=29,28,\ldots,0\) to make the digit \(0\) as many times as possible:
- can we let the \(2^i\)’s place in the binary notation of \(M\) be \(0\)?
If the \(2^i\)’s place of \(a_1,\ldots\), and \(a_N\) are all \(0\), then we can set the \(2^i\)’s place of \(x\) to \(0\) to make the \(2^i\)’s place of \(M\) be \(0\). Same applies to the case where the \(2^i\)’s place of \(a_1,\ldots\), and \(a_N\) are all \(1\). On the other hand, if both \(0\) and \(1\) occur in the \(2^i\)’s place of \(a_1,\ldots\), and \(a_N\), then we cannot let the \(2^i\)’s place of \(M\) be \(0\) (in other words, the \(2^i\)’s place of \(M\) is always \(1\)).
Here, assume that both \(0\) and \(1\) occur in the \(2^i\)’s place of \(a_1,\ldots\), and \(a_N\), and let \(S\) be the set of those whose the digit is \(0\), and \(T\) be those with \(1\). If we let the \(2^i\)’s place of \(x\) be \(0\), then the \(2^i\)’s place of \(a_i \oplus x\) will be \(0\) for each \(a_i \oplus x\), so it is no longer possible that \(a_i \oplus x\) becomes the maximum value of \(A\) after the operation, and we only have to consider the non-negative integers contained in \(T\). Similarly, if we set the \(2^i\)’s place of \(x\) to \(1\), we only have to consider the non-negative integers contained in \(S\). The problem is, we don’t know whether we should preserve \(S\) or \(T\) at the time we process \(2^i\).
In fact, we may try both preserving \(S\) and preserving \(T\). This is because, for each step \(i=29,\ldots,0\), there are only one aforementioned operation that preserves \(a_1,\ldots,a_N\).
The (probably) most general implementation is the following recursive one.
Sample code (C++)
#include <bits/stdc++.h>
using namespace std;
int dfs(int cur,vector<int> a){
if(cur==-1)return 0;
vector<int> S,T;
for(int i=0;i<a.size();i++){
if(((a[i]>>cur)&1)==0)S.push_back(a[i]);
else T.push_back(a[i]);
}
if(S.size()==0)return dfs(cur-1,T);
if(T.size()==0)return dfs(cur-1,S);
return min(dfs(cur-1,S),dfs(cur-1,T)) | (1<<cur);
}
int main() {
int N;
cin>>N;
vector<int> a(N);
for(int i=0;i<N;i++)cin>>a[i];
cout<<dfs(29,a)<<endl;
return 0;
}
posted:
last update: