• 线性基


    线性基

    基本概念:

    线性基的概念见:https://oi.men.ci/linear-basis-notes/

    通俗的讲就是给定你由N个整数构成的整数序列,你可以从中选取一些(至少一个)进行异或((XOR))运算,从而得到很多不同的结果。你能将这(N)个整数压缩成另一个序列,取其中的进行异或((XOR)),得到的结果和之前相同,其中(a[i])二进制的最高位的(1)在第(i)位,且满足一下特殊的性质,这就是线性基。

    构造线性基:

    实现:将整数x插入线性基,将整数x二进制从最高位开始往后枚举,找到最高位i的"1",判断是否能插入bas[i],若不能将x^bas[i],然后继续往后找

    ll bas[N];
    int sz=64;
    bool insert(ll x){
        for(int i=sz;i>=1;i--){
            if((x&(1ll<<(i-1)))==0) continue;
            if(bas[i]) x^=bas[i];
            else bas[i]=x;return true;
        }
        return false;
    }
    

    高斯消元版。

    bool insert(ll x){
        for(int i=sz;i>=1;i--){
            if((x&(1ll<<(i-1)))==0) continue;
            
            if(bas[i]){
            //若如主元j已经存在,用a[j]消去x的第j位然后继续
            	x^=bas[i];
                continue;
            }
            for(int j=1;j<=i-1;j++){
     		//让x当主元i,需要先用第j(j<i)个主元消去x的第j位
     			if(x&(1ll<<(j-1))) x^=bas[j];
            }
            for(int j=i+1;j<=sz;j++){
            //接着用x去消掉第j(j>i)个主元的第i位
                if(bas[j]&(1ll<<(i-1))) bas[j]^=x;  
            }
            bas[i]=x;
            return true;
        }
        return false;
    }
    

    线性基相关性质

    1.求任意子集xor最大值:把线性基中所有元素xor起来。

    ll qryMax(){
        ll ans=0;
        for(int i=1;i<=sz;i++){
            ans^=bas[i];
        }
        return ans;
    }
    

    2.求任意子集xor最小值: 等于最小的主元。

    ll qryMin(){
        for(int i=1;i<=sz;i++){
        	if(bas[i]) return bas[i];    
        }
    }
    

    3.查询第k小的值:把k进行二进制分解,把1对应位置的主元xor起来,注意这里第0小就是0。

    //快速幂
    ll ksm(ll x,ll p){
        ll res=1;
        while(p){
            if(p%2==1) res*=x;
            p/=2;
            x=x*x;
        }
        return res;
    }
     
    ll qry(ll k){
        if(ok) k--; //判断值域是否有0,有0则0为第1小
        if(k<=0) return 0;
        int cnt=count;//线性基大小
        ll res=0;
        for(int i=sz;i>=1;i--){
            if(bas[i]==0) continue;
            cnt--;
            if(k-ksm(2,cnt)<0) continue;
            res^=bas[i];//将k二进制拆分后1的位置
            k-=ksm(2,cnt);
        }
        if(k) return -1;//不存在的k小
        else return res;
    }
    

    4.查询x是否在值域中: 如果x能插入线性基,则x不能被当前线性基xor出来

    5.求任意子集与x进行xor的最大值:从高->低贪心,若xor上a[j]能变大就xor


    相关练习

    【P3812 【模板】线性基】https://www.luogu.com.cn/problem/P3812

    【P4570 [BJWC2011]元素】https://www.luogu.com.cn/problem/P4570

    【acwing229 新nim游戏】https://www.acwing.com/problem/content/231/

    【acwing210 异或运算】https://www.acwing.com/problem/content/212/

    【牛客练习赛76 牛牛数数】https://ac.nowcoder.com/acm/problem/214945

  • 相关阅读:
    [JSOI2007][BZOJ1031] 字符加密Cipher|后缀数组
    leetcode Flatten Binary Tree to Linked List
    leetcode Pascal's Triangle
    leetcode Triangle
    leetcode Valid Palindrome
    leetcode Word Ladder
    leetcode Longest Consecutive Sequence
    leetcode Sum Root to Leaf Numbers
    leetcode Clone Graph
    leetcode Evaluate Reverse Polish Notation
  • 原文地址:https://www.cnblogs.com/kksk/p/14297759.html
Copyright © 2020-2023  润新知