考慮從高到低位做,不斷貪心的一個過程。即假設把當前所有數 \(a_i\) 看成 \(\lfloor \frac{a_i}{2^d} \rfloor\),有當前最優答案 \(ans_d\);現在把所有數看成 \(\lfloor \frac{a_i}{2^{d-1}} \rfloor\),推出下一步的答案 \(ans_{d-1}\)。
假設 \(/2^d\) 時,每一步 xor 完的序列是 \(a_1,a_2,..,a_m\),其中 \(a_i < a_{i+1}\) 且 \(a_m=ans_d\)(這裡忽略了所有 \(=0\) 的數)。從 \(d\to d-1\) 時,現在每個 xor 的數會變為 \(2x\) 或 \(2x+1\),並且會加入一堆 \(1\)。
如果沒有新加入的 1,那麼顯然 \(ans_{d-1} = ans_d\times 2\)。發現新加入的一堆 1 對序列很有影響,因為它們只能被插在“空位”裡,如果“空位”不足就會不得不增加 \(ans_{d-1}\)。
據此可以寫出一份暴力,計算一個陣列 \(a\) 的答案:
int wk(vi o){
n=o.size();For(i,1,n)a[i]=o[i-1],vis[i]=0;
int now=0,res=0;
Rep(i,30,0){
int cnt=0,cnt2=now;
For(j,1,n){
if(!vis[j] && (a[j]>>i&1)) ++cnt,vis[j]=1;
else if(vis[j] && (a[j]>>i&1)) ++cnt2;
}
if(cnt<=cnt2) now+=(cnt2-cnt),res=res*2;
else if(cnt<=cnt2+1) res=res*2+1;
else {
cnt-=(cnt2+1);
now+=cnt;
res+=cnt;
res*=2;
res+=1;
}
// cout<<"res "<<i<<" "<<res<<" "<<now<<"\n";
}
return res;
}