題意:給你一些數,問你是否可以將它們劃分紅兩個集合,使得這兩個集合的異或和之差的絕對值最小。c++
設全部數的異或和爲S,集合A的異或和爲A。spa
首先,S的0的位對答案不形成影響。blog
S的最高位1,所對應的A的那一位必定能夠爲1,不妨設它爲1。get
而後考慮後面的S的1位,儘可能使A對應的位置爲0,這樣才能使S xor A,即B的值最大化,最接近A。it
用線性基來進行斷定,看可否將最高位到目前這位(假定目前這位是0)的這個區間用給定的數線性表出,若是能,就將這位設成0,不然,就將這位設成1。io
媽的,其實整個過程只須要取出最大的線性基,而後儘可能用較小的線性基去消掉除了最高位之外的1便可,獲得的就是A!class
隊友的代碼:集合
#include <bits/stdc++.h> using namespace std; #define FOR(i,a,b) for (LL i=(a);i<=(b);++i) #define ROF(i,b,a) for (LL i=(b);i>=(a);--i) typedef long long LL; LL read(){ LL 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*10+ch-'0'; ch=getchar(); } return x*f; } const LL MAXN=300005; LL n,m,q,a[MAXN],b[MAXN],c[MAXN],f[100]; int main() { LL T=read(); while (T--) { n=read(); m=0; FOR(i,1,n) m^=a[i]=read(); FOR(i,1,n) a[i]&=m; memset(f,0,sizeof(f)); FOR(i,1,n) { ROF(j,62,0) if ((a[i]>>j)&1) { if (!f[j]) { f[j]=a[i]; break; } else { //if (a[i]<f[j]) swap(a[i],f[j]); a[i]^=f[j]; } } } LL x=-1,y=0; ROF(i,62,0) if (f[i]) { x=i; break; } if (x>=0) y=f[x]; //cerr<<y<<' '<<m<<endl; ROF(i,x-1,0) if (f[i]) if ((y>>i)&1) y^=f[i]; cout<<abs(y-(y^m))<<endl; } return 0; } /* 2 4 1 2 3 4 5 3 7 3 9 5 */