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;
}
posted @ 2020-07-22 20:53  GK0328  阅读(100)  评论(0编辑  收藏  举报