题意:
给你 N个数,从中取出若干个进行异或运算 , 求最
后所有可以得到的异或结果中的第k小值N个数高斯消元求出线性基后,设秩为$r$,那么总共可以组成$2^r$中数字(本题不能不选,所以$2^r -1$)
然后如果$k \ge 2^r$就不存在啦
否则一定可以有$k$小,因为现在$1..r$行每行都有一位是1(左面是最高位)
从高到低枚举k的二进制,如果是1就异或上对应的行就行了,最后就是k小值啦
#include#include #include #include #include #include using namespace std;typedef long long ll;const int N=1e4+5,INF=1e9;inline ll read(){ char c=getchar();ll x=0,f=1; while(c<'0'||c>'9'){ if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f;}int n,Q;ll a[N],k,bin[N];void ini(){ bin[0]=1;for(int i=1;i<=60;i++) bin[i]=bin[i-1]<<1;} int now;void Gauss(){ now=1; for(int i=60;i>=0;i--){ int j=now; while(j<=n&&!(a[j]&bin[i])) j++; if(j==n+1) continue; if(j!=now) swap(a[j],a[now]); for(int k=1;k<=n;k++) if(k!=now&&(a[k]&bin[i])) a[k]^=a[now]; now++; } now--;}ll Query(ll k){ //printf("Q %lld\n",k); ll ans=0; if(now!=n) k--; if(k>=bin[now]) return -1; for(int i=1;i<=now;i++) if(k&bin[now-i]) ans^=a[i]; return ans;}int main(){ freopen("in","r",stdin); ini(); int T=read(),cas=0; while(T--){printf("Case #%d:\n",++cas); n=read(); for(int i=1;i<=n;i++) a[i]=read(); Gauss(); Q=read(); while(Q--) printf("%lld\n",Query(read())); }}