1.線性基的本質
線性基的本質就是空間上的一組向量可以用線性變換表示出所有向量。
OI 中常見的主要是異或線性基,就是用若干個數表示一組數的異或和的空間。
2. 異或線性基
2.1 插入
線性基的構建本質上類似高斯消元。
我們設 \(b_i\) 表示主元是 \(i\) 的數,對於一個線性基加入一個數 \(x\),我們從高到低遍歷,假設當前是 \(j\):
-
如果 \(b_j\) 暫時沒有,我們就讓 \(b_j=x\) 並終止。
-
如果有,我們就讓 \(b_j \oplus x \to x\),然後繼續。
我們發現,這樣構建完後線性基大小是 \(O(\log V)\) 的,並且 \(b_i\) 的前 \(i\) 位都是 \(0\)。
其實就是一個上三角的矩陣。
for (int j = 50; j >= 0; j--)
if ((x >> j) & 1)
if (b[j]) //主元確定
x ^= b[j];
else {
b[j] = x;
break;
}
2.2 消元
我們可以將一個線性基所有 \(b_j\) 存在的位置視作變數,剩下的位置都是值。
那麼我們現在 \(b_j\) 其實是若干個變數,我們希望每個 \(b_j\) 只有一個變數。
為了方便後續操作,我們從低到高位消元,使得每個 \(b_j\) 的變數只有一個。
for (int i = 0; i <= 50; i++)
for (int j = i + 1; j <= 50; j++)
if ((b[j] >> i) & 1)
b[j] ^= b[i];
2.3 應用
P3812 【模板】線性基
求最大異或和,我們建出線性基並且消元,我們發現答案就是所有線性基中數的異或和。
提交記錄
LOJ114 k 大異或和
我們發現更高位的線性基對於更低位的是壓倒性勝利,所以我們可以按照字典序的思路一位一位取。這個過程就相當於取走線性基中所有 \(K\) 二進位制位下是 1 的數,注意如果不存在是不計入的。
提交記錄
P4869 albus就是要第一個出場
我們假設總共 \(n\) 個數,線性基中 \(k\) 個數,則每個異或值都出現了 \(2^{n-k}\) 次。
其實不難理解,所有不線上性基中的數都可以被其中的子集表示,那麼每次相當於給 \([k]\) 的子集變成複製一份加上一份中每一個都和一個集合 \(S\) 異或一下,顯然後面是一個一一對映,所以出現次數是相等的。
提交記錄
P4151 [WC2011] 最大XOR和路徑
神題。注意到如果我們走到一半跑去一個環玩一圈再回來,那麼貢獻只有環的異或值。所以我們只用找到所有環的異或和的線性基,在其中找到一個子集和 \(d_n\) 的異或最大即可。
找與某個數異或最大的子集很簡單,每次判斷選上當前的會不會更大即可。
提交記錄
P3292 [SCOI2016] 幸運數字
我們用倍增維護線性基,然後查詢時把 \(O(\log n)\) 個線性基合併即可。合併兩個線性基的時間複雜度是 \(O(\log^V)\) 的,所以時間複雜度 \(O(n \log n \log V + q \log n \log^2 V)\)。
提交記錄