Introduction to linear basis

Posted by Heatmizer20 on Thu, 31 Oct 2019 10:13:29 +0100

Brief explanation

  1. Linear basis under xor:

    Linear basis method:
    From high position to low position, if the linear basis of control I position exists, then a[k]^=p[i]
    Otherwise, p[i] = a[k];break;
    Furthermore, the I-bit of the linear basis other than the linear basis p[i] is changed to 0, and the linear basis with the smallest element is obtained.

  2. Find the k-th small;
    Note that when the element is redundant, 0 can be generated with exclusive or; otherwise, 0 cannot be generated.
    If k is expressed in binary, it can XOR the corresponding linear basis.

  3. The concept of linear basis is similar to space expansion, that is, the whole space can be expanded to be different or operated by the least elements

Reference blog

blog1 blog2

Example HDU3949

code

#include <bits/stdc++.h>
using namespace std;
#pragma GCC optimize("O3")
#define ll long long
#define ull unsigned long long
#define db(x) cout<<#x"=["<<(x)<<"]"<<endl
#define CL(a,b) memset(a,b,sizeof(a))
#define fast() ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define fr0(i,m) for(int i=0;i<m;i++)
#define fr1(i,m) for(int i=1;i<=m;i++)
//author:fridayfang
//Date: July 7, 19
const double esp=1e-8;
const int mod=1e9+7;
const double pi=acos(-1);
const int inf=0x3f3f3f3f;
const int maxn = 1e4 + 5;
const int maxm = 1e6+5;
ll a[maxn];
ll p[64];
int to[100];//
ll t,n,q;
int getBase(){//Processing outgoing basis
    CL(p,0);//Clear 0 first.
    for(ll i=1;i<=n;i++){
        for(int j=63;j>=0;j--){
            if((a[i]>>j)&1){
                if(!p[j]){p[j] = a[i]; break;}
                a[i]^=p[j];
            }
        }
    }
    // Smaller linear basis
    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 is the number of linear bases to[0]...to[cnt-1] has the correct mapping
}
ll getK(ll k,int bound){//Minimum k except 0
    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 #"<<i<<":\n";
        cin>>n;
        for(ll k=1;k<=n;k++) cin>>a[k];
        int cnt = getBase();
        int t = (cnt==(int)n)?0:1;//Unequal means there is redundancy, then it means 0; at this time, the k-1 of the k-th hour is small.
        cin>>q;
        ll k;
        for(ll s=1;s<=q;s++){
            cin>>k; k-=t;
            cout<<getK(k,cnt)<<endl;
        }
    }

    
    return 0;
}

Topics: PHP