bzoj 4269: 再见Xor (高斯消元求解线性基)
2017-01-07 10:22
561 查看
4269: 再见Xor
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 250 Solved: 148
[Submit][Status][Discuss]
Description
给定N个数,你可以在这些数中任意选一些数出来,每个数可以选任意多次,试求出你能选出的数的异或和的最大值和严格次大值。Input
第一行一个正整数N。接下来一行N个非负整数。
Output
一行,包含两个数,最大值和次大值。Sample Input
33 5 6
Sample Output
6 5HINT
100% : N <= 100000, 保证N个数不全是0,而且在int范围内Source
[Submit][Status][Discuss]
题解:分析可得一个数选多次是无意义的,要么选一,要么不选。
那么其实问题就等价成n个数,选其中任意个异或,求最大和次大值。
我们可以用高斯消元求解线性基,会得到一个对角线为1的矩阵
10000
01000
00100
00010
00001 对角线上方可能为0,可能为1,下方一定是0. 那么每行对应的二进制数其实就组成了一组合法的基底。
因为基底中的每一个数的最高位是不同的,而且最高位单调递减,所以用基底表示出的所以数都是不同的。如果出去0的情况不考虑的话,最多会产生2^tot-1个不同的异或和。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 100003
using namespace std;
int n,m;
int a
,b
,tot,zero;
void gauss()
{
tot=zero=0;
for (int i=b[30];i;i>>=1){
int j=tot+1;
while (!(i&a[j])&&j<=n) j++;
if (j==n+1) continue;
tot++;
swap(a[j],a[tot]);
for (int k=1;k<=n;k++)
if (k!=tot&&(a[k]&i)) a[k]^=a[tot];
}
if (tot!=n) zero=1;
}
void solve()
{
int mx=0;
int t=b[tot]-1;
for (int i=1;i<=tot;i++)
if (t&(b[tot-i])) mx^=a[i];
printf("%d ",mx);
mx=0;
t--;
for (int i=1;i<=tot;i++)
if (t&(b[tot-i])) mx^=a[i];
printf("%d\n",mx);
}
int main()
{
freopen("a.in","r",stdin);
scanf("%d",&n);
b[0]=1;
for (int i=1;i<=30;i++) b[i]=b[i-1]*2;
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
gauss();
solve();
}
相关文章推荐
- [高斯消元 线性基] BZOJ 4269 再见Xor
- BZOJ 4269: 再见Xor [高斯消元 线性基]
- [BZOJ4269]再见Xor(高斯消元求线性基+贪心)
- 【bzoj4269】再见Xor 高斯消元求线性基
- 【BZOJ-4269】再见Xor 高斯消元 + 线性基
- 4269: 再见Xor 高斯消元求线性基
- 【BZOJ4269】再见Xor 高斯消元
- BZOJ 4269: 再见Xor|高斯消元
- BZOJ 3105: [cqoi2013]新Nim游戏 [高斯消元XOR 线性基]
- [高斯消元 线性基] BZOJ 2115 [Wc2011] Xor
- BZOJ 2115: [Wc2011] Xor [高斯消元XOR 线性基 图]
- bzoj 4568: [Scoi2016]幸运数字 (高斯消元求解线性基)
- BZOJ 2844: albus就是要第一个出场 [高斯消元XOR 线性基]
- BZOJ 4269 高斯消元求线性基
- [高斯消元 线性基 生成树 随机化权值Xor] BZOJ 3569 DZY Loves Chinese II
- BZOJ 4269 高斯消元求线性基
- BZOJ 4269 再见Xor 高斯消元
- BZOJ_4269_再见Xor_线性基
- 【BZOJ 4269】再见Xor 线性基
- BZOJ 2115 Xor 线性基介绍(高斯消元 xor线性基)