線性基入門

2022-07-14 22:30:33 字數 3181 閱讀 6076

線性基是乙個集合

也就是說線性基是對原集合的壓縮

首先,可以知道

對於集合a = ,將其中的ai(i∈[1,n])用ai ^ aj (j∈[1,n]且j≠i)替換得到集合b =

從集合a中選取任意多個數異或得到的值都能通過在集合b中選取一些數進行異或得到

證:從原集合a中選取一些數異或得到

x = ak1 ^ ak2 ^ ... ^ akm (kj∈[1,n])

如果這些數中不包含ai,那麼這些數也在集合b中,x也能通過在b中取這些數異或得到,

如果包含ai,則ai可以用(ai ^ aj ) ^ aj 替換,故x也能由集合b得到

所以對於任意乙個集合,如果其中有兩個元素的最高位相等,可以用異或將其中乙個元素替換,如此下去,可以讓該集合用某一位作為最高位的數唯一

線性基中不能含有0元素,如果插入乙個元素會使線性基中存在零元素則單獨討論

struct node 

bool insert(ll x)

else }}

flag = 1;

return false;

}//求異或最大值,即從高位向低位掃,如果能使答案更大就異或上該位的值

ll qmax()

return res;

}//如果之前的插入出現了0,則返回0,否則返回線性基中最小的值

ll qmin()

return 0;

}//重構線性基,目的是為了求異或第k小的數

void rebuild() }}

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

}//異或第k小,重構之後的線性基第i位對名次的貢獻即為(1 << i),從低到高看看k的二進位制位第i位是否為1,若為1則要異或上i為的值

ll kth(ll k)

return res;

}};

暴力合併即可

node merge(node n1, node n2) 

res.flag = n1.flag | n2.flag;

return res;

}

給定\(n\)(\(1<=n<=10000)\)個元素,\(q\)(\(1<=q<=10000)\)組詢問,每次詢問異或第k大是多少,不存在則輸出-1

線性基裸題

#include using namespace std;

typedef long long ll;

struct node

bool insert(ll x)

else }}

flag = 1;

return false;

}ll qmax()

return res;

}ll qmin()

return 0;

}void rebuild() }}

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

}ll kth(ll k)

return res;

}};node merge(node n1, node n2)

res.flag = n1.flag | n2.flag;

return res;

}int main()

cse++;

printf("case #%d:\n", cse);

int m;

scanf("%d", &m);

lis.rebuild();

for (int i = 1; i <= m; i++)

}return 0;

}

經過了大量的實驗後,著名法師 dmitri 發現:如果給現在發現的每一種礦石進行合理的編號(編號為正整數,稱為該礦石的元素序號),那麼,乙個礦石組合會產生「魔法抵消」當且僅當存在乙個非空子集,那些礦石的元素序號按位異或起來為零。 例如,使用兩個同樣的礦石必將發生「魔法抵消」,因為這兩種礦石的元素序號相同,異或起來為零。

並且人們有了測定魔力的有效途徑,已經知道了:合成出來的法杖的魔力等於每一種礦石的法力之和。人們已經測定了現今發現的所有礦石的法力值,並且通過實驗推算出每一種礦石的元素序號。

現在,給定你以上的礦石資訊,請你來計算一下當時可以煉製出的法杖最多有多大的魔力。

第一行包含乙個正整數n,表示礦石的種類數。

接下來 n行,每行兩個正整數\(number_i\) 和 \(magic_i\),表示這種礦石的元素序號和魔力值。

\(n<=1000,number_i<=10^,magic_i<=10^4\)

僅包一行,乙個整數:最大的魔力值

3 

1 10

2 20

3 30

50
直接按val從大到小排序,優先插入val大的礦石,(最後線性基每一位都是固定的,所以優先插入val大的是最優的),成功插入統計答案即可

#include using namespace std;

typedef long long ll;

struct node

bool insert(ll x)

else }}

flag = 1;

return false;

}ll qmax()

return res;

}ll qmin()

return 0;

}void rebuild() }}

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

}ll kth(ll k)

return res;

}};node merge(node n1, node n2)

res.flag = n1.flag | n2.flag;

return res;

}const int n = 1050;

struct node1

} a[n];

int main()

sort(a + 1, a + n + 1);

node lis;

ll ans = 0;

for (int i = 1; i <= n; i++)

printf("%lld\n", ans);

return 0;

}

線性基入門

線性基真的是乙個非常神奇的演算法。它可以用於求解乙個集合內的最大異或和,而且效率極高,是 o n log maxnum 的時間複雜度。所以,它還是十分值得一學的。什麼是線性基?對於乙個陣列 a 1a 2.a n 我們可以用 num 1num 2.num 來記錄第乙個二進位制下最高位出現在第 i 位的...

線性基入門學習

前置技能點 線性相關,線性無關 張成 spa nspan span s ss的所有子集 包括空集 的異或和組成的集合,叫做集合s ss的張成。什麼是線性基 線性基可以理解為集合s ss在異或運算中的壓縮,即集合s ss的線性基中的元素進行異或運算可以表示出集合中的元素進行異或運算的所有結果。換句話說...

模板 線性基

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