线性基学习笔记

线性基是干嘛的呢?

给定n个数,求所有数的异或和最大是多少?

求解这类问题的时候,就需要线性基了

个人感觉线性基本身就一种贪心。

首先定义 b a s e [ i ] 表示最高位1在i位的数是什么

对于新进来的数 t m p ,我们先找出他最高位上的1,假设为第 j 位,然后看一下 b a s e [ j ] 有没有数,如果没有,直接将它赋值成 t m p ,如果有,那就 t m p = b a s e [ j ] 就有点像高斯消元 对,把 t m p 这位的1消去(或者说,这个数去掉这位1之后,还能对哪些 b a s e 作贡献),那么我们考虑,经过这个处理, t m p 要么被加入了base,要么变成了0(就是他可以被之前的数异或得到)

m a x 的时候,我们就贪心即可

#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>同时线性基的任何一个非空子集都不会使得其 x o r 和为0

2>果有很多个数,我们可以构出这些数的线性基,那么这个线性基可以通过互相xor,能够构出原来的数可以相互xor构出的所有的数。就可以减少判断的时间和次数。

猜你喜欢

转载自blog.csdn.net/y752742355/article/details/80660400