1.什么是线性基:
线性基是一个数的集合,并且每个序列都拥有至少一个线性基,取线性基中若干个数异或起来可以得到原序列中的任何一个数。
(异或:相同则为0,不同为1)
(关于异或的小性质:如果a^b^c=0,那么a^b=c,如果a^b=c,则a^c=b)
2.线性基三大性质:
(1)原序列里面的任意一个数都可以由线性基里面的一些数异或得到
(2)线性基里面的任意一些数异或起来都不能得到 0
(3)线性基里面的数的个数唯一,并且在保持性质一的前提下,数的个数是最少的
(2)线性基里面的任意一些数异或起来都不能得到 0
(3)线性基里面的数的个数唯一,并且在保持性质一的前提下,数的个数是最少的
试题链接:http://www.acmicpc.sdnu.edu.cn/problem/show/1592
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <map>
#include <set>
using namespace std;
#define ll long long
int n;
ll p[60],a[100000];
void insert(ll v)
{
for(int i=52;i>=0;i--)
{
if(((1ll<<i)&v)!=0)
// 1<<i -> 1左移i位,即2的i次方
// 这句话的意思是:把1转换成long long 类型,然后取(2^i)
// &v代表:在二进制中如果有与其不同的,就进行接下来的操作
{
if(p[i]) v^=p[i];
else { p[i]=v; return; }
}
}
}
int main()
{
cin >> n;
for (int i=1;i<=n;i++)
{
cin >> a[i];
insert(a[i]);
}
// for(int i=1;i<=n;++i) scanf("%lld",&a[i]),insert(a[i]);
ll ans=0;
for(int i=52;i>=0;--i)
{
if(p[i]) ans = max(ans,ans^p[i]);
}
// 求完线性基后,贪心求异或最大值,高位数字的贡献要大于它后面所有地位数字的贡献,当前位数上的数异或答案后使得答案更大时,就更新
printf("%lld\n",ans);
return 0;
}



京公网安备 11010502036488号