1. 程式人生 > >HDU-3949 XOR

HDU-3949 XOR

思路:先求出a[]的線性基f[],然後將線性基的每一位進行消除使其只有本身的那一位,在將f[i]中非0的全部移動f[1,m]中,m為非0的個數,這樣對於第K個數,就是將K轉為二進位制中為1的f[]異或起來即可。另外還要處理有0的情況,這時需要將K-=1

Code :

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long LL;

int n,m,Q,T;
int pp;
LL f[65];
void Insert(LL x);
void Build();
LL Query(LL k);

int main()
{
	scanf("%d",&T);
	for(int t=1;t<=T;++t)
	{
		memset(f,0,sizeof(f));
		pp=m=0;
		scanf("%d",&n);
		LL x;
		for(int i=0;i<n;++i)
		{
			scanf("%lld",&x);
			Insert(x);
		}
		Build();
		printf("Case #%d:\n",t);
		scanf("%d",&Q);
		while(Q--){
			scanf("%lld",&x);
			x-=pp;
			if(x>=((LL)1<<m))	printf("-1\n");
			else	printf("%lld\n",Query(x));
		}
	}
	
	return 0;
}

void Insert(LL x)
{
	for(int i=63;i>=0;--i)
		if(x>>i){
			if(!f[i]){
				f[i]=x;	break;
			}
			x^=f[i];
		}
	if(!x)	pp=1;
}

void Build()
{
	for(int i=0;i<=63;++i)
		for(int j=i+1;j<=63;++j)
			if((f[j]>>i)&1)	f[j]^=f[i];
	for(int i=0;i<=63;++i)
		if(f[i])	f[m++]=f[i];
}

LL Query(LL k)
{
	int i=0;
	LL res=0;
	while(k){
		if(k&1)	res=res^f[i];
		k>>=1;	++i;
	}
	return res;
}