HDOJ3949 XOR 线性基

XOR

Solution:

线性基模板,求异或空间第k大(小)。

只讲一下需要注意的是:

求解线性基时,应按照从高往低位消元,这样才能保证基的单调性。

#include<string>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define RG register
#define IL inline
#define int long long
#define DB double
using namespace std;

IL int gi() {
	char ch=getchar(); RG int x=0,w=0;
	while(ch<'0'||ch>'9') {if (ch=='-') w=1;ch=getchar();}
	while(ch>='0'&&ch<='9') x=x*10+(ch^48),ch=getchar();
	return w?-x:x;
}

const int N=1e5+10;

int n,Q,cnt,ans,flag,a[N];

IL void Gauss_Jordan() {
	RG int i,j,l;
	cnt=0,flag=0;
	// 此处i一定要从大到小枚举...
	// 否则不能保证基的单调性...
	for(i=63;i>=0;--i) {
		for(j=cnt+1,l=0;j<=n;++j)
			if((a[j]>>i)&1) {l=j;break;}
		if(!l) continue;
		swap(a[l],a[++cnt]);
		for(j=1;j<=n;++j)
			if(j!=cnt&&((a[j]>>i)&1)) a[j]^=a[cnt];
	}
	for(i=cnt+1;i<=n;++i)
		if(!a[i]) {flag=1;break;}
}

signed main()
{
	RG int i,j,x,T=gi(),Case=0;
	while(T--) {
		memset(a,0,sizeof(a));
		for(i=1,n=gi();i<=n;++i) a[i]=gi();
		Gauss_Jordan();
		printf("Case #%lld:\n",++Case);
		for(Q=gi();Q;--Q) {
			x=gi(),ans=0;
			if(flag) --x;
			if(x>(1ll<<cnt)-1) puts("-1");
			else {
				for(j=1;j<=cnt;++j)
					if((x>>j-1)&1) ans^=a[cnt-j+1];
				printf("%lld\n",ans);
			}
			// 将x二进制分解...
		}
	}	
 	return 0;
}

posted @ 2019-04-04 17:42  薄荷凉了夏  阅读(333)  评论(2编辑  收藏  举报