bzoj4269 再见Xor

再见Xor

Time Limit: 10 Sec Memory Limit: 512 MB

Description

给定N个数,你可以在这些数中任意选一些数出来,每个数可以选任意多次,试求出你能选出的数的异或和的最大值和严格次大值。

Input

第一行一个正整数N。
接下来一行N个非负整数。

Output

一行,包含两个数,最大值和次大值。

Sample Input

3
3 5 6

Sample Output

6 5

HINT

100% : N <= 100000, 保证N个数不全是0,而且在int范围内

学了个叫线性基的东西。。。
有篇博客真的写的好:https://blog.sengxian.com/algorithms/linear-basis
唯一要说的就是线性基中的数不一定在原来的集合里(最开始的智障理解233)
博客真的很稳,顺着网线Orz


#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
int n, ans, ini[maxn], bas[35];
int main()
{
	scanf("%d", &n);
	for(int i = 1; i <= n; ++i) scanf("%d", &ini[i]);
	
	for(int i = 1; i <= n; ++i)
		for(int t = 31; t >= 1; --t)
			if((ini[i] >> (t - 1)) & 1){
				if(!bas[t]){
					bas[t] = ini[i];					
					for(int j = 1; j < t; ++j){
						if(bas[j] && (bas[t] >> (j - 1) & 1)) bas[t] ^= bas[j];
					}
					for(int j = 31; j > t; --j){
						if(bas[j] >> (t - 1) & 1) bas[j] ^= bas[t];
					}
					break;
				} 
				else ini[i] ^= bas[t];
			}
	
	for(int i = 1; i <= 31; ++i) ans ^= bas[i]; cout << ans << " ";
	for(int i = 1; i <= 31; ++i) if(bas[i]) {ans ^= bas[i]; break;} cout << ans;
	return 0;
} 

posted @ 2018-04-02 22:28  沛霖  阅读(123)  评论(0编辑  收藏  举报