Problem Description
XOR is a kind of bit operator, we define that as follow: for two
binary base number A and B, let C=A XOR B, then for each bit of C, we
can get its value by check the digit of corresponding position in A
and B. And for each digit, 1 XOR 1 = 0, 1 XOR 0 = 1, 0 XOR 1 = 1, 0
XOR 0 = 0. And we simply write this operator as ^, like 3 ^ 1 = 2,4 ^
3 = 7. XOR is an amazing operator and this is a question about XOR. We
can choose several numbers and do XOR operatorion to them one by one,
then we get another number. For example, if we choose 2,3 and 4, we
can get 2^3^4=5. Now, you are given N numbers, and you can choose some
of them(even a single number) to do XOR on them, and you can get many
different numbers. Now I want you tell me which number is the K-th
smallest number among them.
Input
First line of the input is a single integer T(T<=30), indicates there
are T test cases. For each test case, the first line is an integer
N(1<=N<=10000), the number of numbers below. The second line contains
N integers (each number is between 1 and 10^18). The third line is a
number Q(1<=Q<=10000), the number of queries. The fourth line contains
Q numbers(each number is between 1 and 10^18) K1,K2,……KQ.
Output
For each test case,first output Case #C: in a single line,C means the
number of the test case which is from 1 to T. Then for each query, you
should output a single line contains the Ki-th smallest number in
them, if there are less than Ki different numbers, output -1.
Sample Input
2
2
1 2
4
1 2 3 4
3
1 2 3
5
1 2 3 4 5
Sample Output
Case #1:
1
2
3
-1
Case #2:
0
1
2
3
-1
Hint
If you choose a single number, the result you get is the number you
choose. Using long long instead of int because of the result may
exceed 2^31-1.
翻译
T组数据
每组数据给出n个数,从中选出几个数进行异或运算,多次询问第k小的数是多少
题解
线性基的另一种求法
我们知道高斯消元进行的实际上也是基础行变换,消元后得到的异或空间是不会变的
于是我们可以直接对这n个数的二进制拆分后高斯消元解异或方程组
由高斯消元的性质可以知道对于第(i,i)个主元,在第i列有且仅有(i,i)的值为1
抽象回这些数我们可以发现每个数分别代表了一个二进制位,即异或时必须要异或这些数才能得到这个二进制位的贡献
对k进行二进制拆分。我们可以发现,对于k的二进制最低位,如果为1,我们即异或高斯消元后排在最后的数,倒数第二位为1时我们异或倒数第二个数,以此类推。手玩一下可以玩出结论
对于0的情况要进行特判,判断高斯消元后是否存在空行即是否能通过异或方程得到0
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
int n,m;
LL f[11000];
int p[70];
int main()
{
int T;scanf("%d",&T);
for(int tt=1;tt<=T;tt++)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%lld",&f[i]);
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)if(f[i]<f[j])swap(f[i],f[j]);
if(f[i]==0)break;
for(int k=62;k>=0;k--)
{
if(f[i]&(1LL<<k))
{
for(int j=1;j<=n;j++)if(f[j]&(1LL<<k) && j!=i)f[j]=f[j]^f[i];
break;
}
}
}
int sum=0;
bool bk=false;
for(int i=1;i<=n;i++)
{
if(!f[i])bk=true;
else sum++;
}
printf("Case #%d:\n",tt);
scanf("%d",&m);
while(m--)
{
LL num;scanf("%lld",&num);
if(bk)num--;
memset(p,0,sizeof(p));int ln=0;
while(num)p[++ln]=num%2,num>>=1;
if(ln>sum){printf("-1\n");continue;}
LL ans=0;int last=sum;
for(int i=1;i<=ln;i++,last--)if(p[i]==1)ans^=f[last];
printf("%lld\n",ans);
}
}
return 0;
}