分析:异或消元最后得到的是一组基,那么这些数能够异或出来的值,都是这些基线性组合形成的数,注意,消元以后得到的基是有顺序的(排序以后也能得到顺序),这个时候由于每一位都不可能进位,所以最大的基肯定是第
2row
小的,
row
是矩阵的秩。包含
0
,这个很容易理解,本题的要点就是
附上代码:(其实我是来存代码的,一开始我的xor使用高斯消元的模板写的 o(63∗63∗n) 复杂度,还啰嗦,学习了新的模板,果然不一样!!! o(63∗n) )
代码中注释部分也可以,但是明显发现不如没注释的优美!!!(包含的想法也不太一样, k <script type="math/tex" id="MathJax-Element-831">k</script>直接代表了哪几个数可取)
#include <bits/stdc++.h>
#define LL long long
#define FOR(i,x,y) for(int i = x;i < y;++ i)
#define IFOR(i,x,y) for(int i = x;i > y;-- i)
using namespace std;
const int maxn = 10010;
LL x[maxn];
int n,q;
int xorguass(LL a[]){
int row = 0;
for(int i = 62;i >= 0;-- i){
int j;
for(j = row;j < n;++ j) {if(a[j] & (1LL<<i)) break;}
if(j != n){
swap(a[row],a[j]);
for(j = 0;j < n;++ j){
if(j == row) continue;
if(a[j] && a[j]&(1LL<<i)){
a[j] ^= a[row];
}
}
++ row;
}
}
return row;
}
void work(){
int row = xorguass(x);
LL mx;
if(row < n) mx = 1LL<<row;
else mx = (1LL<<row)-1;
scanf("%d",&q);
while(q --){
LL k;
scanf("%I64d",&k);
if(k > mx) {printf("-1\n");continue;}
LL ans = 0;
/**
if(row == n) ++ k;
FOR(i,0,row){
if(!k) break;
if(k > (1LL<<(row-1-i))){
ans ^= x[i];
k -= (1LL<<(row-1-i));
}
}
**/
if(row < n) -- k;
FOR(i,0,row) if(k&(1LL<<(row-1-i))) ans ^= x[i];
printf("%I64d\n",ans);
}
}
int main()
{
//freopen("test.in","r",stdin);
int T,tCase = 0; scanf("%d",&T);
while(T--){
printf("Case #%d:\n",++tCase);
scanf("%d",&n);
FOR(i,0,n) scanf("%I64d",&x[i]);
work();
}
return 0;
}