魔改版線性基解決此類問題。
聯絡線性空間的性質,我們直接可以構造出這樣的基:
\[100000
\\010000
\\000010
\\000001
\]使得每個基的最高位是唯一的,我們的目的是要能夠保證從上往下一直異或一直變大,所以不能使基出現這樣的情況:
\[100001
\\000001
\]
乙個不能從上往下一直異或一直變大的例子。考慮如何構造\(kth\) 大(小),考慮這樣的性質,我們記\(a_i\)表示從下往上第\(i\)個基,顯然從\(0\)開始,如果我們異或了\(a_x\),那麼我們可以保證我們會比這個線性空間內\(2^\)個值都要大,直接考慮從上往下查詢,類似樹上倍增。
考慮無解的情況,顯然當我們發現\(k \ge 2^\)時就無解了。
然而我們有乙個問題,那就是我們預設\(0\)是可以被表示出來的,然而我們知道,當給定元素全部互為不相關時,這個時候就不存在乙個\(0\)會被表示出來了。那麼我們可以特判一下即可 。
好,那麼如何構造從上往下一直異或一直變大的基呢?魔改一下就好了。具體看**。
分析複雜度:我們把魔改操作的\(log^2\)看做常數吧...那就是\(o(nlogn)\)
當然你如果不承認魔改操作是常數,那就繼續魔改\(upd\)函式,也可以做到\(nlogn\)。具體就是加入的時候從小往大加。
下面的第\(k\)小,轉換為第\(k\)大用\(2^\)減去即可。
#include using namespace std;
typedef long long ll;
template inline ccf qr(ccf ret)
namespace bs
inline ll size()
inline void set()
inline void upd(ll x) else
x ^= data[t];
}if(not x) }}
inline ll que(ll k)
}return ret;
}inline void clear()
inline void debug()
cout << endl;}};
inline void init()
}bs::base qaq;
int main()
HDU 3949 異或線性基
題目鏈結 題意 有n nn個數和q qq個詢問,每個詢問給出乙個正整數k kk,問這n nn個數異或組合出的所有數中第k kk小的是什麼數,若不存在則輸出 1 1 1。思路 首先構建出這n nn個數的異或線性基。假設非零線性基共有tot totto t個,從小到大排列後,對於第x xx個線性基,前1...
51Nod 1577 異或湊數(線性基)
description 從左到右一共 n 個數,數字下標從1到 n 編號。一共m 次詢問,每次詢問是否能從第 l 個到第 r個數中 包括第 l 個和第 r個數 選出一些數使得他們異或為 k 資料量比較大。輸入請用掛 int read 輸出請用pu tsinput 單組測試資料。第一行乙個整數n 05...
線性基(處理集合異或的強力工具)
看了好多篇關於線性基的部落格,只是說明了怎麼求線性基,但是大都沒有說明為什麼這樣求線性基。有乙個集合 s t的滿足下面條件的乙個最小子集a a的所有子集的異或和的值域與t的所有子集的異或和的值域相同,那麼a就是t的線性基。1 張成 s的所有子集,其異或和的所有可能的結果組成的集合,為s的張成,記作s...