线性基入门

线性基入门

简要讲解

  1. xor下的线性基:

    线性基求法:
    从高位向低位求,如果控制i位的线性基存在,则a[k]^=p[i]
    否则 p[i] = a[k];break;
    进一步,将除线性基p[i]外的线性基的i位变为0;则得到元素最小的线性基;

  2. 求第k小;
    注意当元素存在冗余,则可以异或生成0;反之,不能生成0
    将k进行2进制表示,则可对应相应的线性基进行异或

  3. 线性基的概念类似于空间张成,即通过最少的元素能张成异或运算下的整个空间

参考博客

blog1 blog2

例题HDU3949

code

#include 
using namespace std;
#pragma GCC optimize("O3")
#define ll long long
#define ull unsigned long long
#define db(x) cout<<#x"=["<<(x)<<"]"<=0;j--){
            if((a[i]>>j)&1){
                if(!p[j]){p[j] = a[i]; break;}
                a[i]^=p[j];
            }
        }
    }
    // 更小的线性基
    int cnt = 0;
    for(int j=0;j<=63;j++){
        if(!p[j]) continue;
        for(int i=j+1;i<=63;i++){
            if((p[i]>>j)&1) p[i] = p[i]^p[j];
        }
        to[cnt++]=j;
    }
    return cnt;//cnt是线性基的个数 to[0]...to[cnt-1]有正确的映射
}
ll getK(ll k,int bound){//除0外的最k小
    int t = 0;
    ll tmp = k;
    ll ans = 0;
    while(tmp){
        if(t>=bound) return -1;
        if(tmp&1) ans^=p[to[t]];
        tmp = tmp>>1;
        t++;
    }
    return ans;
}



int main(){
    fast();cin>>t;
    for(ll i=1;i<=t;i++){
        cout<<"Case #"<>n;
        for(ll k=1;k<=n;k++) cin>>a[k];
        int cnt = getBase();
        int t = (cnt==(int)n)?0:1;//不等表示有冗余,则可表示0;此时第k小时第k-1小
        cin>>q;
        ll k;
        for(ll s=1;s<=q;s++){
            cin>>k; k-=t;
            cout<

转载于:https://www.cnblogs.com/fridayfang/p/11148308.html

你可能感兴趣的:(线性基入门)