線性基學習筆記
阿新 • • 發佈:2018-12-22
pre 貢獻 mes 通過 fin git while line for
線性基是幹嘛的呢?
給定n個數,求所有數的異或和最大是多少?
求解這類問題的時候,就需要線性基了
個人感覺線性基本身就一種貪心。
首先定義\(base[i]\)表示最高位1在i位的數是什麽
對於新進來的數\(tmp\),我們先找出他最高位上的1,假設為第\(j\)位,然後看一下\(base[j]\)有沒有數,如果沒有,直接將它賦值成\(tmp\),如果有,那就\(tmp^=base[j]\)就有點像高斯消元 對,把\(tmp\)這位的1消去(或者說,這個數去掉這位1之後,還能對哪些\(base\)作貢獻),那麽我們考慮,經過這個處理,\(tmp\)要麽被加入了base,要麽變成了0(就是他可以被之前的數異或得到)
求\(max\)的時候,我們就貪心即可
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #define ll long long using namespace std; inline ll read() { ll x=0,f=1;char ch=getchar(); while (!isdigit(ch)) {if (ch==‘-‘) f=-1; ch=getchar();} while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-‘0‘;ch=getchar();} return x*f; } ll n,tmp; ll base[110]; int main() { n=read(); for (int i=1;i<=n;i++){ tmp=read(); for (int j=63;j>=0;j--) { if (tmp & (1LL << j)) { if (!base[j]) { base[j]=tmp; break; } tmp^=base[j]; } } } ll ans=0; for (int i=63;i>=0;i--) { if (ans<(ans ^ base[i])) ans^=base[i]; } cout<<ans; return 0; }
這裏補充一個線性基的性質:
1>同時線性基的任何一個非空子集都不會使得其\(xor\)和為0
2>果有很多個數,我們可以構出這些數的線性基,那麽這個線性基可以通過互相xor,能夠構出原來的數可以相互xor構出的所有的數。就可以減少判斷的時間和次數。
線性基學習筆記