將一個數列分成兩部分求一種分組方式使得兩部分異或和的差距最小

 

1.貪心考慮二進制下每個數字的每一位,偶數個的話,那麼就不用考慮這一位的分組,怎麼分配在答案裏這一位都是0

2.只考慮奇數的位,那麼答案中一定是  A-B 的形式

假設A>B  那麼首先另A=0,那麼異或上最大的線性基,並且盡力吧現在的A的非最高位,盡力變成0,因爲A和B是一種異或

A變的小的話A,B也會更接近。--->abs(A-B)更小

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
#define en '\n'
#define ll long long
#define maxn 200007
ll  d[65],a[maxn];
ll rd() {ll t;scanf("%lld",&t);return t;}
void insert(ll x){
    for(int i=62;i>=0;--i){
        if((x>>i)&1){
            if(!d[i]){
                d[i]=x;
                break;
            }
            else x^=d[i];
        }
    }
}
signed main()
{
    #ifdef swt
    freopen("input2.txt","r",stdin);
    #endif
    int T=rd();
    #define mem(a,b) memset(a,b,sizeof(a))
    while(T--){
        mem(d,0);
        int n=rd();ll sm=0;
        for(int i=1;i<=n;i++){
            a[i]=rd();sm^=a[i];
        //    insert(a[i]);
        }
        for(int i=1;i<=n;i++){
            a[i]&=sm;
            insert(a[i]);
        }
        int index=0;
        ll tem=0;
        for(int i=62;i>=0;--i){
            if(d[i]){
                index=i;
                tem=d[i];break;
            }
        }
        for(int i=index-1;i>=0;--i){
            if(((tem>>i)&1) and d[i]){
                tem=tem^d[i];
            }
        }
        cout<<abs(tem-(sm^tem))<<en;
    }
    return 0;
}

 

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