1. 程式人生 > >線性基學習筆記

線性基學習筆記

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構出的所有的數。就可以減少判斷的時間和次數。

線性基學習筆記