[模板]線性基
阿新 • • 發佈:2018-12-04
int getchar() 它的 turn 繼續 def lin 相同 掃描
用途
處理關於子集的異或和的問題,比如子集異或和的最大值,或者能不能異或出某個數
原理
從一堆數中處理出一組線性無關(?)的數,使得這些數能異或出的數和原來能異或出的數相同
線性基中,以每個位置為最高位1的數(最多)只有一個,這樣就保證了線性無關
做法
依次處理每個數,對於x,從大到小掃描它的每一位,當掃到第i位為1時:
若線性基中沒有最高位為i的數,則把x插到線性基中,結束掃描
若有,則把x異或上那個數,繼續做
這樣做,如果一個數最終沒有被插入線性基中,證明它已經能被線性基中的數表示
而插到線性基中的數,也一定是幾個原數的異或和
最後我如果想找能異或出的最大的數,那就從高到低掃線性基中的每個數,如果異或上能使答案變大,就異或上,畢竟機不可失時不再來
例題
luogu3812
1 #include<bits/stdc++.h> 2 #define CLR(a,x) memset(a,x,sizeof(a)) 3 #define MP make_pair 4 using namespace std; 5 typedef long long ll; 6 typedef unsigned long long ull; 7 typedef pair<int,int> pa; 8 const int maxn=55; 9 10 inline ll rd(){ 11 ll x=0;char c=getchar();int neg=1; 12 while(c<‘0‘||c>‘9‘){if(c==‘-‘) neg=-1;c=getchar();} 13 while(c>=‘0‘&&c<=‘9‘) x=x*10+c-‘0‘,c=getchar(); 14 return x*neg; 15 } 16 17 int N; 18 ll a[maxn],x[maxn]; 19 20 int main(){ 21 //freopen("","r",stdin); 22 int i,j,k;23 N=rd(); 24 for(i=1;i<=N;i++) a[i]=rd(); 25 for(i=1;i<=N;i++){ 26 for(j=50;j>=0;j--){ 27 if(a[i]&(1ll<<j)){ 28 if(!x[j]){ 29 x[j]=a[i];break; 30 }else a[i]^=x[j]; 31 } 32 } 33 } 34 ll ans=0; 35 for(i=50;i>=0;i--){ 36 if((ans^x[i])>ans) ans^=x[i]; 37 } 38 printf("%lld\n",ans); 39 return 0; 40 }
如果您像我一樣容易忘記寫break的話,可以考慮不寫else,反正如果我這次插進去了,再異或上我自己就變成了0,就相當於break了
[模板]線性基