题目:
题解:
我们要将线性基改造成每一位相互独立。
具体操作就是如果i < j,aj的第i位是1,就将aj异或上ai。
经过一系列操作之后,对于二进制的某一位i。只有ai的这一位是1,其他都是0。
所以查询的时候将k二进制拆分,对于1的位,就异或上对应的线性基。
最终得出的答案就是k小值。
注意0要单独判断,如果加入线性基过程中有0才有0,不然就没有
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
using namespace std;
LL b[70],a[10005],p[70];
LL qurry(LL k)
{
LL ans=0;
for (int i=0;i<=60;i++)
if (k>>i&1) ans^=p[i];
return ans;
}
int main()
{
int T,n,q;scanf("%d",&T);
for (int T_T=1;T_T<=T;T_T++)
{
memset(b,0,sizeof(b));bool flag=0;int cnt=0;
printf("Case #%d:\n",T_T);
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%lld",&a[i]);
for (int i=1;i<=n;i++)
for (int j=60;j>=0;j--)
if (a[i]>>j&1)
{
if (!b[j]){b[j]=a[i];break;}
else
{
a[i]^=b[j];
if (!a[i]) flag=1;
}
}
for (int i=60;i>=0;i--)
for (int j=i-1;j>=0;j--)
if (b[i]>>j&1) b[i]^=b[j];
for (int i=0;i<=60;i++) if (b[i]) p[cnt++]=b[i];
scanf("%d",&q);
while (q--)
{
LL k;scanf("%lld",&k);
if (flag) k--;
if (k>=(1ll<<cnt)) {printf("-1\n");continue;}
if (!k) {printf("0\n");continue;}
printf("%lld\n",qurry(k));
}
}
}