Codeforces Round #613 (Div. 2) D. Dr. Evil Underscores(遞歸+思維)

題目鏈接:https://codeforces.com/contest/1285/problem/D

題目大意:給n個數字,用一個X跟所有數字異或,使得到的數字的最大值最小

題目思路:太久沒寫題,水平掉太快了。。。這題我的想法是從高位開始,如果遇到全1或全0那麼就是0,如果有的0有的1,那麼就嘗試這位不異或和異或1得到的結果,看看最大值哪個小就按照哪個來,但是感覺這樣沒考慮後面的,應該是錯的,看了半天題解纔看懂。。太菜了。。
其實整體思路都是對的,就只差最後一步。如果這一位既有1,又有0,那麼答案中這一位一定是1,爲啥呢。因爲你想要最大值,如果這一位不異或,有1的出來頂,如果異或,那麼這位是0的出來頂,總能把這一位頂出1。但是,右邊咋取呢?這一位的1,究竟是因爲異或了出來的,還是沒異或出來的?這就有兩種情況,需要遞歸。因爲如果只有一位數字的話,結果是肯定的,所以先遞歸到最低位,然後用之後的答案不斷更新高位,以此獲得結果,感覺這題非常好。

以下是代碼:

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define ll long long
const int MAXN = 1e5+5;
const int MOD = 1e9+7;
int a[MAXN];
int n;
vector<int>v;
int solve(vector<int>v,int pos){
    if(pos<0)return 0;
    vector<int>l,r;
    int len=v.size();
    rep(i,0,len-1){
        if(((1<<pos)&v[i])==(1<<pos))l.push_back(v[i]);
        else r.push_back(v[i]);
    }
    if(!l.size())return solve(r,pos-1);
    if(!r.size())return solve(l,pos-1);
    return min(solve(l,pos-1),solve(r,pos-1))+(1<<pos);
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    v.clear();
    while(cin>>n){
        rep(i,1,n)cin>>a[i],v.push_back(a[i]);
        cout<<solve(v,30)<<endl;
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章