题目链接:https://cn.vjudge.net/problem/HDU-3949
题意:查询异或结果第k小的数
题解:因为有异或结果为0的情况,所以在插入的时候,判断下是否每一个位置都有线性基了,如果都有了,那就说明能异或得到0,然后如果有0的存在的话,进行查询第k大函数的时候注意把k减一
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
ll a[N], p[65], p1[65], p2[65];
int flag;
void build(int n) {
for(int i = 0; i <= 60; i++) p[i] = 0;
for(int i = 1; i <= n; i++) {
for(int j = 60; j >= 0; j--) {
if((a[i] >> j) & 1) {
if(!p[j]) {
p[j] = a[i];
break;
}
a[i] ^= p[j];
}
}
if(a[i] == 0) flag = 1;
}
}
int n, q;
int cnt;
void rebuild() {
cnt = 0;
for(int i = 60; i >= 0; i--)
for(int j = i - 1; j >= 0; j--)
if((p[i] >> j) & 1)
p[i] ^= p[j];
for(int i = 0; i <= 60; i++)
if(p[i])
p[cnt++] = p[i];
}
ll querykth(ll k) {
ll ans = 0;
if(k >= (1LL << cnt)) return -1;
for(int i = 60; i >= 0; i--)
if((k >> i) & 1)
ans ^= p[i];
return ans;
}
bool judge(ll k) {
for(int i = 60; i >= 0; i--)
if((k >> i) & 1)
k = k ^ p[i];
return k == 0;
}
int main() {
int T, ca = 1;
ll k;
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
for(int i = 1; i <= n; i++)
scanf("%lld", &a[i]);
flag = 0;
build(n);
rebuild();
printf("Case #%d:\n", ca++);
scanf("%d", &q);
while(q--) {
scanf("%lld", &k);
if(flag) k--;
printf("%lld\n", querykth(k));
}
}
return 0;
}