集合\(s\)有子集\(t\)
使得\(s\)的任意子集的元素的亦或和
都能被\(t\)的某個子集的元素亦或得到
且\(t\)的任何子集的亦或和不為\(0\)
\(t\)就是\(s\)的線性基
顯然\(s\)的子集亦或和的值域與\(t\)的子集亦或和的值域相等
比如說\(s=\\) (二進位制)
那麼\(t\)就是\(\\)
高斯消元
高斯消元可以看做求一組n階向量的線性基的過程
最後求出的矩陣的秩,就是線性基的元素個數
消完元後的線性無關組,就是一組線性基
求\(xor\)線性基與此類似,只是用乙個\(long long\)來代替高斯消元的\(n\)階向量
高斯消元最後保留的是乙個類似上三角矩陣的東西,
與此同理,
\(s=\\) (二進位制)
\(t=\\)
如上面的例子,最高位在0位上的只有1,在1位上的只有10,在2位上的只有100
具體求法:
依次將數插入到線性基,
如果該數的最高位1上對應的線性基元素為0,
那麼就將這個數作為該位的線性基元素,插入成功,退出
否則將這個數亦或該位上的線性基元素,
這時這個數的最高位1變小,就繼續往下找
直至該數插入成功
或者被亦或成了0,說明這個數可以被其他幾個數的亦或和表示出來,插入失敗
**
#define ll long long
ll p[maxn]; //最高位1在第i位上的線性基元素,如果沒有,就為0
inline void ins(ll x)
luogup3812
二、查詢某個數是否在亦或和的值域集合內
如果能成功插入這個數,就不在值域集合內,
否則就在值域集合內
inline bool check(ll x)
int t,n,m;
ll p[maxn];
bool flag;
inline void ins(ll x){ //插入乙個數x
for(int i=maxlog;i>=0;--i)
if(x&(1ll<=0;--i)
if(p[i])
for(int j=i-1;j>=0;--j)
if(p[i]>(p[i]^p[j]))
p[i]^=p[j];
int cnt=-1;
for(int i=0;i<=maxlog;++i)
if(p[i]) p[++cnt]=p[i]; //將不為0的p[i]排名
m=read();
while(m--){
x=read();
if(flag) --x; //0佔了乙個名次
if(x>=(1ll《以上只是線性基應用的幾個例子,只要明白了原理,我們可以用線性基解決很多問題
練習題彩燈
新nim遊戲
元素luogup4869
luogup4151
線性基學習筆記
線性基是幹嘛的呢?給定n個數,求所有數的異或和最大是多少?求解這類問題的時候,就需要線性基了 個人感覺線性基本身就一種貪心。首先定義ba se i bas e i 表示最高位1在i位的數是什麼 對於新進來的數tm p tmp 我們先找出他最高位上的1,假設為第 j j 位,然後看一下ba se j ...
線性基 學習筆記
includeusing namespace std using ll long long const int maxn 5e5 5 原來的數 const int maxbit 63 ll a maxn 原來的數 ll p maxbit p j 第j位為最高位1的數 最高位1在第j位的數 int m...
線性基 學習筆記
按位計算,如果相同記為0,不同記為1。如果,a b c,c b a 交換律結合律 對於任何數,x x 0,x 0 x 對 於一 段序列a n,異或 和為a1 a2 an 對於一段序列a n,異或和為a 1 a 2 a n 對於一段序列 an 異或和為 a1 a2 an 設t s,所有 這樣的子 集t...