【bzoj4296】再见Xor
2016-11-21 13:05
183 查看
4269: 再见Xor
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 176 Solved: 107
[Submit][Status][Discuss]
Description
给定N个数,你可以在这些数中任意选一些数出来,每个数可以选任意多次,试求出你能选出的数的异或和的最大值和严格次大值。Input
第一行一个正整数N。接下来一行N个非负整数。
Output
一行,包含两个数,最大值和次大值。Sample Input
33 5 6
Sample Output
6 5【题解】
这算是一道高斯消元求线性基的模板题,我尽量讲得详细点。
首先把每个数拆成二进制的形式,用矩阵表示。
如样例:
0 1 1
1 0 1
1 1 0
然后高斯消元:
0 1 1 交换前2行 1 0 1 处理2和3行 1 0 1 处理第3行 1 0 1
1 0 1 =======> 0 1 1 ========> 0 1 1 =======> 0 1 1
1 1 0 1 1 0 0 1 1 0 0 0
此时只能保证第二行二进制第二位为1,记录temp=2
然后把矩阵的前temp行求异或和,就是最大值ans,然后ans^a[temp]就是次大值。
可以yy一下,或者自己动手推推。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<ctime> 7 #include<algorithm> 8 using namespace std; 9 #define MAXN 100010 10 int n,ans,a[MAXN]; 11 inline int read() 12 { 13 int x=0,f=1; char ch=getchar(); 14 while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getchar();} 15 while(isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();} 16 return x*f; 17 } 18 void guess() 19 { 20 int temp=0; 21 for(int i=(1<<30),j;i;i>>=1)//枚举2进制每一位 22 { 23 for(j=temp+1;j<=n;j++) if(a[j]&i) break;//找到当前二进制位上是1的第一个数 24 if(j>n) continue;//找不到,继续 25 swap(a[++temp],a[j]);//高斯消元固有的 26 for(int j=1;j<=n;j++) if(j!=temp&&(a[j]&i)) a[j]^=a[temp];//处理其他行 27 } 28 for(int i=1;i<=temp;i++) ans^=a[i]; 29 printf("%d %d\n",ans,ans^a[temp]); 30 } 31 int main() 32 { 33 //freopen("cin.in","r",stdin); 34 //freopen("cout.out","w",stdout); 35 n=read(); 36 for(int i=1;i<=n;i++) a[i]=read(); 37 guess(); 38 return 0; 39 }
相关文章推荐
- 【bzoj4296】再见Xor
- BZOJ 4269: 再见Xor|高斯消元
- [高斯消元 线性基] BZOJ 4269 再见Xor
- 【BZOJ 4269】再见Xor 线性基
- BZOJ 4269: 再见Xor
- bzoj 4269 再见Xor
- BZOJ 4269 再见Xor 高斯消元
- 【bzoj4269】再见Xor 高斯消元求线性基
- [bzoj4269]再见xor
- 【BZOJ 4269】再见Xor
- 【BZOJ4269】再见Xor 高斯消元
- 【BZOJ4269】再见Xor
- [线性基] BZOJ 4269: 再见Xor
- bzoj 4269: 再见Xor (高斯消元求解线性基)
- 【BZOJ-4269】再见Xor 高斯消元 + 线性基
- [BZOJ4269]再见Xor(高斯消元求线性基+贪心)
- BZOJ_4269_再见Xor_线性基
- BZOJ 4269 再见Xor
- BZOJ 4269: 再见Xor [高斯消元 线性基]
- BZOJ 4269: 再见Xor