HDU 3949 XOR

才想起来线性基还没学过呢

其实我并没有怎么搞懂线性基到底咋用而且这个求法也是奥妙重重

我们每次考虑向当前已有的基中插入一个数

显然基是之前的数异或的结果

所以从高位到低位判断,如果这一位已经有基了,那么我们把这个数与基异或一下,这个数的这一位就Biu地不见了

否则我们就把这个数(已经被异或得不成人形了)插到这一位上去

同时线性基要满足一些性质才好用,比如说每个基最简化,于是我们还要refresh一下已经形成的基

(以上都是我口胡的大家不要信)

然后对于询问什么的二进制拆分一下(其实我也不知道怎么搞,我抄的代码)

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
ll base[70];
bool ins_base(ll x){
	for(int i=63;i>=0;i--)
	if(x>>i&1){
		if(!base[i]){
			base[i]=x;
			for(int j=0;j<=63;j++)
			for(int k=j+1;k<=63;k++)
			if(base[k]>>j&1)base[k]^=base[j];
			return true;
		}else x^=base[i];
	}
	if(!x)return false;
	else return true;
}
int main(){
	//freopen("a.in","r",stdin);
	//freopen("a.out","w",stdout);
	int T;scanf("%d",&T);
	for(int kase=1;kase<=T;kase++){
		printf("Case #%d:\n",kase);
		memset(base,0,sizeof(base));
		int n;ll x;bool flag=false;
		scanf("%d",&n);
		while(n--){
			scanf("%lld",&x);
			if(!ins_base(x))flag=true;
		}
		int cnt=0;
		for(int i=0;i<=63;i++)
		if(base[i])base[cnt++]=base[i];
		int q;scanf("%d",&q);
		while(q--){
			scanf("%lld",&x);
			x-=flag;
			if(x>>cnt)puts("-1");
			else{
				ll ans=0;
				for(int i=0;i<cnt;i++)
				if(x>>i&1)ans^=base[i];
				printf("%lld\n",ans);
			}
		}
	}
	return 0;
}


你可能感兴趣的:(HDU 3949 XOR)