我眼中的通俗易懂的線性基

線性基

我在學這個的時候不明白基是一個什麼東西,然後我想了很久沒法理解究竟什麼叫做線性基,千萬不要理解成是一個序列選一些數使之異或和最大。。

首先
你得有一些高一數學基礎比如說向量,我們可以任意定義兩條單位長度的向量,這兩條能夠成該平面直角座標系的所有向量,這兩條向量稱之爲基底。
那麼,線性基差不多也是這個意思,

線性基的定義


(百度百科)

通過原集合S的某一個最小子集S1使得S1內元素相互異或得到的值域與原集合S相互異或得到的值域相同。

emm怎麼說呢,線性基能夠成這個序列所能產生的任何xor值,即線性基
類似於基底對於平面直角座標系的基底

爲什麼呢?首先我們要明白xor的一個性質
^即xor的運算符
1.a ^b=b ^a
2.如果
a ^b=c
那麼
a ^c=b
c ^b=a

根絕這兩個性質,我們可以由任意一組下面的s[i] 來得到其他的數
我這裏用一個s數組來維護線性基
s[x] 代表x 位是1,且x 位是該數的最高位。
類似於反着來的lowbit(x) (樹狀數組)

我們可以來模擬一組數據

先上代碼

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#define ll long long
using namespace std;
const int maxn=1e6+5;
const int mod=1e9+7;
ll a[maxn],sum,s[65];
void insert(ll val)
{
    for(int i=60;i>=0;i--)
      if (val&(1ll<<i))
        if (!s[i])
          {
            s[i]=val;
            return;
          }
        else val^=s[i];
}
int main()
{
    ll n,j,k;
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)
        scanf("%lld",&a[i]);
    for(int i=1;i<=n;i++)
      insert(a[i]);
    ll ans=0;
    for (int i=60; i>=0; i--)
      if ((ans^s[i])>ans) ans^=s[i];
    printf("%lld\n",ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章