线性基总结

线性基三个性质:

  1. 原序列里面的任意一个数都可以由线性基里面的一些数异或得到。
  2. 线性基里面的任意一些数异或起来都不能得到0
  3. 线性基里面的数的个数唯一,并且在保持性质一的前提下,数的个数是最少的

构造:arr数组为线性基数组,x为要插入的元素。

void add(ll arr[],ll x) {
    for (int i = 63; i >= 0; i--) {
        if (x & (1ll<<i)) {
            if (arr[i]) x^=arr[i];
            else {
                arr[i] = x;
            }
        }
    }
}

  arr数组中存的元素arr[i]为二进制最高位1在第i+1位,如果这个位置已经有值了的话就对异或之后的值进行判断。

 

可用于求一组数异或后的最大值:

ll work()
{
    ll ans=0;
    for(int i=63;i>=0;i--)
    if((ans^d[i])>ans) ans^=arr[i];
    return ans;
 }  

 

也可用于求一组数异或后的最小值:

ll work() {
    for (int i = 0; i <= n; i++) {
        if (arr[i]) return arr[i];
    }
}

 

 

 

求第k小:

void work()//处理线性基
{
    for(int i=1;i<=60;i++)
    for(int j=1;j<=i;j++)
    if(d[i]&(1<<(j-1)))d[i]^=d[j-1];
}
ll k_th(ll k)
{
    if(k==1&&tot<n)return 0;//特判一下,假如k=1,并且原来的序列可以异或出0,就要返回0,tot表示线性基中的元素个数,n表示序列长度
    if(tot<n)k--;//类似上面,去掉0的情况,因为线性基中只能异或出不为0的解
    work();
    ll ans=0;
    for(int i=0;i<=60;i++)
    if(d[i]!=0)
    {
        if(k%2==1)ans^=d[i];
        k/=2;
    }
}

 

题目明天再写~

模板题
更多好题(难度非递增):
BJWC 2011 元素   |  题解
SCOI 2016 幸运数字  | 题解
TJOI 2008 彩灯 

 

  参考:https://blog.csdn.net/a_forever_dream/article/details/83654397

 

posted @ 2019-07-31 22:27  19呀  阅读(227)  评论(0编辑  收藏  举报