线性基

介绍:

理解起来挺简单的一个东西

基于xor产生的东西

线性基实际上是一个集合

这个集合xor能得到的值和原集合相同

构造方法:

我们用f[i]记录最高位1在第i位的数

插入一个新元素时,我们从最高位开始扫描

如果f[i]是空的,那么f[i]=x

否则x^=f[i]

1.求xor最大值

这个只要贪心就可以了,如果加入这个有优势就加进来

2.求xor最小值

就是线性基中的最小值

3.求xor k小值

前两个都是很显然的,这个还是有一定难度的

我们会发现 对于每个线性基 我们有选和不选两种状态 将其看成一个二进制

能把它看成二进制的令一个重要因素在于,后面的位的影响比前面要小

例如二进制中2^1<2^2<2^3...... 这里同样

那么我们要求k小值

也就是二进制的k小

所以每个数取不取就看k这一位是否为1就可以了

模板代码:

位运算多打括号

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define N 200 
ll a[N],f[N],n;
int main()
{
    freopen("noi.in","r",stdin);
    freopen("noi.out","w",stdout);
    cin>>n;
    for (ll i=1;i<=n;i++) cin>>a[i];
    for (ll k=1;k<=n;k++)
    {
      ll x=a[k];
      for (ll i=60;i;i--)
        if ((x>>(i-1))&1)
        {
            if (f[i]) x^=f[i];
            else
            {
                f[i]=x;
                break;
            }
        }
    }
    ll ans=0;
    for (ll i=60;i>=1;i--)
    {
        if ((f[i]^ans)>ans) ans=f[i]^ans;   //位运算多括号啊 比>优先级还低。。。
    }
    cout<<ans;
    return 0;
}
原文地址:https://www.cnblogs.com/yinwuxiao/p/8807937.html