地址:http://acm.hdu.edu.cn/showproblem.php?pid=3949
思路:先求出a[]的线性基f[],然后将线性基的每一位进行消除使其只有本身的那一位,在将f[i]中非0的全部移动f[1,m]中,m为非0的个数,这样对于第K个数,就是将K转为二进制中为1的f[]异或起来即可。另外还要处理有0的情况,这时需要将K-=1
Code :
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long LL;
int n,m,Q,T;
int pp;
LL f[65];
void Insert(LL x);
void Build();
LL Query(LL k);
int main()
{
scanf("%d",&T);
for(int t=1;t<=T;++t)
{
memset(f,0,sizeof(f));
pp=m=0;
scanf("%d",&n);
LL x;
for(int i=0;i<n;++i)
{
scanf("%lld",&x);
Insert(x);
}
Build();
printf("Case #%d:\n",t);
scanf("%d",&Q);
while(Q--){
scanf("%lld",&x);
x-=pp;
if(x>=((LL)1<<m)) printf("-1\n");
else printf("%lld\n",Query(x));
}
}
return 0;
}
void Insert(LL x)
{
for(int i=63;i>=0;--i)
if(x>>i){
if(!f[i]){
f[i]=x; break;
}
x^=f[i];
}
if(!x) pp=1;
}
void Build()
{
for(int i=0;i<=63;++i)
for(int j=i+1;j<=63;++j)
if((f[j]>>i)&1) f[j]^=f[i];
for(int i=0;i<=63;++i)
if(f[i]) f[m++]=f[i];
}
LL Query(LL k)
{
int i=0;
LL res=0;
while(k){
if(k&1) res=res^f[i];
k>>=1; ++i;
}
return res;
}