HDU 3949 XOR [线性基|高斯消元]


目录

题目链接

HDU 3949 XOR

题解

hdu3949XOR
搞死消元找到一组线性无关组
消出对角矩阵后
对于k二进制拆分
对于每列只有有一个1的,显然可以用k的二进制数直接异或得到第k大
对于一列由多个1的,由于二进制性质,由于2的幂+1次方比2的(1到幂)的和要大,所以不影响大小

代码

#include<queue> 
#include<cstdio> 
#include<cstring> 
#include<algorithm> 
using namespace std; 
inline int read() { 
	int x = 0,f = 1; 
	char c = getchar(); 
	while(c < '0' || c > '9') c = getchar(); 
	while(c <= '9' && c >= '0') x = x * 10 + c - '0',c = getchar(); 
	return x * f; 
} 
void print(int x) { 
	if(x < 0) { 
		putchar('-'); 
		x = -x; 
	} 
	if(x >= 10) print(x / 10); 
	putchar(x % 10 + '0'); 
} 
const int maxn = 10007; 
int a[maxn],tot = 0,zero = 0; 
int n; 
void guass() { 
	tot = zero = 0; 
	for(int i = 60;i >= 0;-- i)  {
		int j = tot + 1; 
		while(!((a[j] >> i) & 1) && j <= n)++ j; 
		if(j == n + 1) continue; 
		tot ++; 
		swap(a[tot],a[j]); 
		for(j = 1;j <= n;++ j) { 
			if(j != tot && ((a[j] >> i) & 1)) a[j] ^= a[tot]; 
		} 
	} 
	if(tot != n) zero = 1; 
} 
int query(int x) { 
	int ans = 0; 
	x -= zero; 
	if(!x) return 0; 
	if(x >= (1ll << tot)) return -1; 
	for(int i = 1;i <= tot;++ i) { 	
		if(x & (1ll << (tot - i))) ans ^= a[i]; 
	} 
	return ans; 
} 
void work() { 
	n = read(); 
	for(int i = 1;i <= n;++ i) a[i] = read(); 
	guass(); 
	int m = read(); 
	while(m --) { 
		int x = read(); 
		print(query(x)); 
		putchar('
'); 
	} 
} 
main() {
	int T = read(); 
	for(int i = 1;i <= T;++ i) { 
		memset(a,0,sizeof a); 
		printf("Case #%d:
",i);  
		work(); 
	} 
} 
原文地址:https://www.cnblogs.com/sssy/p/9839671.html