首页 > 其他 > 详细

线性基总结

时间:2019-08-01 01:03:07      阅读:111      评论:0      收藏:0      [点我收藏+]

线性基三个性质:

  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

 

线性基总结

原文:https://www.cnblogs.com/l999q/p/11279571.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!