首先求出线性基,并且进一步尽可能的使的p[i]除了第i位是1以外,取余全0,尽量使得除了主对角线其余元素都为0;
之后判断线性基的秩,若秩!=元素个数,说明元素之间异或会出现0的情况,那么需要将k-1,因为此时剩余的非零向量间是无法异或出0的情况的,0是最小的异或值;
假设秩为x,那么向量间相互异或的可能情况有1<<x种,若k>=(1<<x),则说明不可异或出,否则将k二进制拆分,若这一位为1则异或对应的p[i];
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const double epos=1e-8;
const int maxn=1e4+7;
//int b[maxn];
ll a[maxn];
ll p[64];
//int hhh[maxn][64];
void Linear_basis(int n){
//for(int i=1;i<=n;++i)
// a[i]=b[i];
memset(p,0,sizeof(p));
//memset(hhh,0,sizeof(hhh));
for(int i=1;i<=n;++i)
for(int j=63;j>=0;--j)
if(a[i]&(1LL<<j)){
if(p[j]) a[i]^=p[j];
else{ p[j]=a[i];break;}
}
//检验,列向量;
// for(int i=63;i>=0;--i)
// cout<<p[i]<<" ";
// cout<<endl;
// cout<<" Linear_basis "<<endl;
//
// for(int i=63;i>=0;--i){
// for(int j=63;j>=0;--j)
// if(p[i]&(1LL<<j)) hhh[3-j][3-i]=1;
// }
// for(int i=0;i<64;++i){
// for(int j=0;j<64;++j)
// cout<<hhh[i][j]<<" ";
// cout<<endl;
// }
// cout<<endl;
}
vector<ll>v;
int zhi,n;
void part2(int n){
//for(int i=1;i<=n;++i)
// a[i]=b[i];
memset(p,0,sizeof(p));
//memset(hhh,0,sizeof(hhh));
for(int i=1;i<=n;++i)
for(int j=63;j>=0;--j)
if(a[i]&(1LL<<j)){
if(p[j]) a[i]^=p[j];
else{
p[j]=a[i];
//先考虑消自身,再去消别的向量;
/*对于自身低位的1如果能消掉就消,对于其他高位有1的向量,
考虑利用自身消去其他向量这一位是1的情况;*/
for(int k=j-1;k>=0;--k)
if((p[j]&(1LL<<k))&&p[k]) p[j]^=p[k];
for(int k=j+1;k<64;++k)
if(p[k]&(1LL<<j)) p[k]^=p[j];
break;
}
}
v.clear();
zhi=0;
for(int i=0;i<=63;++i) if(p[i]){v.push_back(p[i]);++zhi;}
//检验,列向量;
// for(int i=63;i>=0;--i)
// cout<<p[i]<<" ";
// cout<<endl;
// cout<<" part2 "<<endl;
//
// for(int i=63;i>=0;--i){
// for(int j=63;j>=0;--j)
// if(p[i]&(1LL<<j)) hhh[3-j][3-i]=1;
// }
// for(int i=0;i<64;++i){
// for(int j=0;j<64;++j)
// cout<<hhh[i][j]<<" ";
// cout<<endl;
// }
// cout<<endl;
}
ll myfind(ll k){
if(zhi!=n) --k;
if(k>=(1LL<<zhi)) return -1;
ll ans=0;
for(int i=0;i<zhi;++i)
if(k&(1LL<<i)) ans^=v[i];
return ans;
}
int main(){
int t;
int m;
ll k;
scanf("%d",&t);
for(int h=1;h<=t;++h){
printf("Case #%d:\n",h);
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%lld",&a[i]);
part2(n);
scanf("%d",&m);
while(m--){
scanf("%lld",&k);
printf("%lld\n",myfind(k));
}
}
return 0;
}