Luogu3812 【模板】线性基
https://www.luogu.com.cn/problem/P3812
参考\(blog\):https://www.cnblogs.com/vb4896/p/6149022.html
线性基
首先,对于序列\(a,b,c\),它与\(a,b,b\quad xor \quad c\)能异或出的数的种类相同。
所以我们插入一个数时,可以与原序列中的数瞎异或。
我们可以使序列中的数的二进制最高位不同(这种情况是唯一的)。
然后贪心取就好了。
上述做法在代码\(solve1\)函数中。
\(update:\)更新了高斯消元求线性基,可以判别那些列有主元(不是很懂主元相关),在代码\(solve2\)函数中。
\(Code:\)
#include<iostream>
#include<cstdio>
#include<algorithm>
#define N 55
#define ll long long
using namespace std;
int n,t;
ll ans,a[N],g[N];
void solve1()
{
for (int i=1;i<=n;++i)
{
for (int j=50;j>=0;--j)
if ((a[i] >> j) & 1)
{
if (g[j])
a[i]^=g[j]; else
{
g[j]=a[i];
break;
}
}
}
for (int i=50;i>=0;--i)
ans=max(ans,ans^g[i]);
printf("%lld\n",ans);
}
void solve2()
{
t=n;
for (int i=1;i<=n;++i)
{
for (int j=i;j<=n;++j)
if (a[j]>a[i])
swap(a[j],a[i]);
if (!a[i])
{
t=i-1;
break;
}
for (int j=50;j>=0;--j)
if ((a[i] >> j) & 1)
{
for (int k=1;k<=n;++k)
if (k!=i && (a[k] >> j) & 1)
a[k]^=a[i];
break;
}
}
for (int i=1;i<=t;++i)
ans=max(ans,ans^a[i]);
printf("%lld\n",ans);
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;++i)
scanf("%lld",&a[i]);
solve2();
return 0;
}