这题算是一道经典的模板题
方法的话看代码很容易看出在干什么
至于为什么我在这里瞎吹一下:
首先,通过我的prepare函数,我们可以保证基的每一位都最多只有一个1
我们从以下xor的性质可以得到,只要是基里面,无论怎么改都是一个合法的基
所以最后我们的基还是合法的
于是问题就变成了一个十分简单的配对问题
我们知道在倒三角每往上多配对一个,值肯定会变大
于是就可以确定大小了
接着我们在将k变成二进制,就知道是有哪些位了
讲得很绕啊
code:
#include<cstdio>
#include<cstring>
typedef long long LL;
const LL N=10005;
LL g[65];
LL T;
bool tf=false;
void ins (LL x)
{
for (LL u=62;u>=0;u--)
if (x>>u&1)
{
if (g[u]==-1) {g[u]=x;return ;}
x=x^g[u];
}
tf=true;
return ;
}
LL d[N],cnt;
void prepare ()
{
for (LL u=62;u>=0;u--)
{
if (g[u]==-1) continue;
for (LL i=u-1;i>=0;i--)
{
if (g[i]==-1) continue;
if (g[u]>>i&1) g[u]^=g[i];
}
}
for (LL u=0;u<=62;u++)
if (g[u]!=-1)
d[cnt++]=g[u];
return ;
}
LL solve (LL k)
{
if (tf==true) k--;
if (k==0) {return 0;}
if (k>=(1LL<<cnt)) return -1;
LL ans=0;
for (LL u=62;u>=0;u--)
if (k>>u&1)
{
ans=ans^d[u];
}
return ans;
}
int main()
{
scanf("%lld",&T);
for (LL O=1;O<=T;O++)
{
tf=false;
cnt=0;memset(g,-1,sizeof(g));
memset(d,0,sizeof(d));
LL n;
scanf("%lld",&n);
while (n--)
{
LL a;
scanf("%lld",&a);
ins(a);
}
prepare();
LL m;
printf("Case #%d:\n", O);
scanf("%lld",&m);
while (m--)
{
LL k;
scanf("%lld",&k);
printf("%lld\n",solve(k));
}
}
return 0;
}