正题
题目链接:https://loj.ac/problem/114
题目大意
nnn个数,求所有非空子集的kkk小异或和。
解题思路
我们考虑处理一下线性基,我们知道对于did_idi是一定在第iii位为111。
对于一个i>ji>ji>j且did_idi的第jjj位为111时,我们就让di=dixordjd_i=d_i\ xor\ d_jdi=di xor dj。这样对于每个did_idi在iii之前的ddd无论如何异或也不会比did_idi大,did_idi之后无论如何异或也不会比did_idi小。
这样对于第zzz个不等于000的did_idi如果kkk的第zzz位为111就可以异或上这个did_idi。
要记得判断是否能异或出000
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
ll n,m,d[60];
bool flag;
void add(ll x){for(ll i=50;i>=0;i--)if((x>>i)&1){if(d[i])x^=d[i];else{d[i]=x;flag|=(x==0);return;}}flag=1;return;
}
ll kth(ll x){if(flag)x--;ll ans=0;for(ll i=0;i<=50;i++)if(d[i]){if(x&1)ans^=d[i];x>>=1;}if(x)return -1;return ans;
}
int main()
{scanf("%lld",&n);for(ll i=1;i<=n;i++){ll x;scanf("%lld",&x);add(x);}for(int i=0;i<=50;i++)for(int j=0;j<i;j++)if(d[i]&(1ll<<j))d[i]^=d[j];scanf("%lld",&m);while(m--){ll x;scanf("%lld",&x);printf("%lld\n",kth(x));}
}