zoukankan      html  css  js  c++  java
  • 线性基入门

    推荐博客 : https://www.cnblogs.com/vb4896/p/6149022.html

          https://blog.csdn.net/qaq__qaq/article/details/53812883

    这个我觉得不是很好理解,花了一天半得时间,稍微懂了一点,写个博客

    首先我们要明确这个线性基可以解决什么样得问题,例如动态增加元素,求解集合异或最大值

    这里有一个增加操作,向里面增加一个元素,从最高位向下扫,当扫到 1 ,并且线性基中该位置为 0 ,则将这个元素加入到线性基中,否则用此元素去异或线性基中的数

    int val[maxn][40];
    void insert(int b[], int x){
        for(int i = 30; i >= 0; i--){
            if (x>>i&1){
                if (!b[i]) {b[i] = x; break;}
                else x ^= b[i];
            }
        }
    }
    

     合并

    void unit(int x,int y){
        // 将 x 暴力插入到 y 中 
        for(int i=30;i>=0;--i)
            if(val[x][i]) insert (val[y],val[x][i]);
    }
    

     查询

    查询一个元素是否再集合中x

    最大值

    从高位到低位去扫一遍

    int cal(int p){
        int ans = 0;
        for(int i = 30; i >= 0; i--){
            if ((ans^val[i]) > ans) {
                ans ^= val[i];
            }
        }
        return ans;
    }
    

     最小值

    int query(){
        for(int i = 0; i <= 30; i++){
            if (val[i]) return val[i];
        }
        return 0;
    }
    

     求解第K大

    将线性基重新构造一下

    ll cnt = 0;
    ll p[65];
    
    void rbuild(){
        for(ll i = 60; i >= 0; i--){ 
            for(ll j = i-1; j >= 0; j--){
                if ((1ll<<j)&a[i]) a[i] ^= a[j];
            }
        }
        
        for(ll i = 0; i <= 60; i++){
            if (a[i]) p[cnt++] = a[i];
        }
    }
    
    ll query(ll x){
        if (x >= (1ll<<cnt)) return -1;
        ll ans = 0;
        for(ll j = 60; j >= 0; j--){
            if ((1ll<<j)&x){
                ans ^= p[j];
            }
        }
        return ans;
    }
    
    东北日出西边雨 道是无情却有情
  • 相关阅读:
    bzoj1103[POI2007]大都市meg
    bzoj1098[POI2007]办公楼biu
    bzoj1102[POI2007]山峰和山谷Grz
    POI刷题记录
    语法-指针
    dp-最长公共子序列
    如何判断素数
    C++的map用法
    stl-优先队列
    C++和Java的stack语法
  • 原文地址:https://www.cnblogs.com/ccut-ry/p/8964431.html
Copyright © 2011-2022 走看看