「線性基」學習筆記and亂口胡總結
阿新 • • 發佈:2019-04-22
typedef www 如果 http 如何 const void 能夠 否則
介於我們在插入的時候都是無法匹配的時候,異或上這一位上的數,那麽就保證了我們的這個數能夠達到自己能用的最大貢獻。
還以為是什麽非常高大上的東西花了1h不到就學好了
線性基
線性基可以在\(O(nlogx)\)的時間內計算出\(n\)個數的最大異或和(不需要相鄰)。
上述中\(x\)表示的最大的數。
如何實現
定義\(p[i]\)表示在二進制下從最高位開始第一個出現\(1\)的數。
當前我們將一個數插入線性基中。
如果\(x\)的最高位的\(1\)還沒有被插入過,那麽就在這一位上插入\(x\)。
如果沒有被插入過,那麽就異或上這一位上的數。
查詢操作:從最高位上開始貪心。
如果異或這一位上的數可以讓答案更大,那麽就異或,否則就異或。
貪心驗證
因為我們從高位往低位貪心,所以不需要考慮低位上的數會讓高位上的數變小的情況。
代碼
【洛谷模板區】
#include <bits/stdc++.h> using namespace std; const int BIT = 63; const int N = 52; typedef long long ll; ll a[N], p[BIT + 2]; int n; void ins(ll x) { for (int i = BIT; ~i; i --) { if ((x >> i) == 0) continue; if (!p[i]) { p[i] = x; break; } x ^= p[i]; } } int main() { cin >> n; for (int i = 1; i <= n; i ++) cin >> a[i]; for (int i = 1; i <= n; i ++) ins(a[i]); for (int i = 0; i <= BIT; i ++) cout << i << " " << p[i] << endl; cout << endl; ll ans = 0; for (int i = BIT; ~i; i --) if ((ans ^ p[i]) > ans) ans ^= p[i]; cout << ans << endl; return 0; }
「線性基」學習筆記and亂口胡總結