數學 線性基

2022-05-11 05:45:09 字數 3149 閱讀 3774

這是乙個看起來很像gauss-jordan消元法裡面的形式(行最簡形矩陣)的線性基,和其他人的gauss消元法裡面的形式(上三角形矩陣)看起來並不一樣

d[i] 表示掌管二進位制第i位(1ll<= 0; --i)

++n;

d[i] = x;

for(int j = 0; j < i; ++j)

for(int j = i + 1; j < len; ++j)

return true;}}

z = 1;

return false;

}bool query(ll x)

return false;}}

return x == 0;

}// maximal

ll max()

// minimal

ll min()

}ll kthmin(ll k)

}return k ? -1 : res;

}ll size()

void show(int sl = len)

}printf("\n");

}} lb;n:線性基中非零值有多少個

z:是否可以組成0

設值域為 \(a\) 。

嘗試往線性基中插入乙個x:

問題就是x是否能被當前的線性基中的數字線性表示。

所以對於x的每個非0的位,都去找對應的d[i]和他異或,注意這樣可能會引入新的位,所以規定從高到低異或就可以每次消去一位。當其可以被線性基中的數字表示時,那麼再加上這個數本身就可以表示0了,就置z標記為1。否則要把這個剩餘的數字插入到對應的d[i]中,然後用比它低位的d[j]消去d[i]中帶有d[j]的位,再用d[i]消去比它高位的d[j]中的帶有d[i]的位。(注意順序,要先確保比i低的被掌管的位已經被消為0)。

最大值:

當不存在非零值時,判斷是否可以組成0,若0都沒有,那麼就是空集。否則,由於是行最簡形,所以就所有的d[i]都異或起來。

最小值:

當不存在非零值時,判斷是否可以組成0,若0都沒有,那麼就是空集。判斷是否能夠組成0,有0就是0,否則輸出最小的那個基底。

第k小值:

判斷是否能夠組成0,有0的話0就是最小值,--k。然後在非零的裡面找第k小的。

然後從最小的基底開始往高位掃,每次k的最低位是奇數,就選中最小的基底,否則就不選。若最後k沒有被消除完,則說明非0的值不足k個。

合併:(改變d[i]的定義後)把規模小的那個線性基插入到大的那個,或者都直接暴力掃一遍。

insert x=41

n=1 z=0

d[05]=000000101001

insert x=35

n=2 z=0

d[05]=000000100011

d[03]=000000001010

insert x=190

n=3 z=0

d[07]=000010010111

d[05]=000000100011

d[03]=000000001010

insert x=1924

n=4 z=0

d[10]=011100010011

d[07]=000010010111

d[05]=000000100011

d[03]=000000001010

insert x=737

n=5 z=0

d[10]=010101000110

d[09]=001001010101

d[07]=000010010111

d[05]=000000100011

d[03]=000000001010

insert x=1388

n=6 z=0

d[10]=010101000101

d[09]=001001010101

d[07]=000010010100

d[05]=000000100000

d[03]=000000001001

d[01]=000000000011

insert x=1238

n=7 z=0

d[10]=010001000001

d[09]=001001010101

d[08]=000100000100

d[07]=000010010100

d[05]=000000100000

d[03]=000000001001

d[01]=000000000011

insert x=686

n=8 z=0

d[10]=010000000100

d[09]=001000010000

d[08]=000100000100

d[07]=000010010100

d[06]=000001000101

d[05]=000000100000

d[03]=000000001001

d[01]=000000000011

好好用哦。

提供乙個用vector的實現:

struct lb 

bool insert(ll x)

z = 1;

return false;

}bool query(ll x)

// maximal

ll max()

// minimal

ll min()

ll kthmin(ll k)

return k ? -1 : res;

}ll size()

void show(int sl = len)

printf("\n");

}} lb;

合併線性基的時候記得順便把z標記也合併。

當可以離線查詢時,可以維護[i,r]的所有線性基,當++r時從右往左掃瞄所有「當前字尾線性基」並嘗試插入,因為每個線性基最多被插入成功log次,當插入失敗時說明這個位置的值可以替代當前r的值,更前面的也會插入失敗。

struct lb 

void insert(ll x, int xpos) else

x ^= d[i];}}

}}

// maximal

ll max()

} lb;

模板 數學 線性基

includeusing namespace std define ll long long const int mn 60 ll a mn tmp mn bool flag 該線性基能否表示0 嘗試向線性基中插入乙個值 void ins ll x else x a i flag true 判斷該線...

模板 線性基

難度較大,請勿棄療 給定n個整數 數字可能重複 求在這些數中選取任意個,使得他們的異或和最大。n 50sample input33 21sample output 3看上去莫名其妙地想貪心。給些定義 s 為無符號整數集 即s n 記為 xor sum s x or s um s s1 s2 s s ...

模板 線性基

給定n個整數 數字可能重複 求在這些數中選取任意個,使得他們的異或和最大。線性基模板可解決 將n個整數看做集合a 線性基即為集合a的子集 線性基中每個元素的異或方案唯一,也就是說,線性基中不同的異或組合異或出的數都是不一樣的。線性基的二進位制最高位互不相同。這樣我們先構造出線性基 然後貪心的去搞最大...