标签:logs 方程组 bool 相互 ... log 复杂 xor 一个
1.线性基的异或集合中每个元素的异或方案唯一。
2.线性基二进制最高位互不相同。
3.线性基中元素互相异或,异或集合不变。
摘自百度文库
线性基能相互异或得到原集合的所有相互异或得到的值。
线性基是满足性质1的最小的集合
线性基没有异或和为0的子集。
证明:
反证法:设线性基S={a1,a2...,an};
若有子集a1^a2^...^at=0,则a1=a2^a3^...^at,则舍弃a1后一定能通过剩余的元素异或出所有需要a1参与异或的值。设Y=a1^X,因为{a1,a2,...,an}是一组线性基,X一定能由a2...an中相互异或得来。
Y=a1^X=a2^a3^...^at^X,将X中在a2...at中出现的元素删去,在a2...at中未出现的元素加入,则也能异或得到Y,所以a1于线性基无用,与线性基是最小子集的定义矛盾。
所以:线性基没有异或和为0的子集。
线性基的本质是高斯消元,通过xor操作,将加减变成mod2意义下,也就是xor了。
解xor方程组用到了矩阵转置,也就是判断他们是不是线性无关的方法。我们需要维护一个线性无关的子集,并且删去的元素可以通过这个子集xor得到。
并且通过压位复杂度从63*63*63*n->63*n
//luogu3812
#include<bits/stdc++.h>
#define ll long long
#define cls(a,b) memset(a,b,sizeof(b))
using namespace std;
struct lb {
ll d[61],p[61];
lb() {cls(d,0);cls(p,0);}
bool insert(ll n) {
for(int i=60;i>=0;i--) {
if((1ll<<i)&n) {
if(!d[i]) {
d[i]=n;
break;
}
n^=d[i];
}
}
return n>0;
}
ll get_mx() {
ll ans=0;
for(int i=60;i>=0;i--)
if((ans^d[i])>ans)
ans^=d[i];
return ans;
}
ll get_mn() {
for(int i=0;i<=60;i++)
if(d[i])
return d[i];
return 0;
}
}b;
ll n,x;
main() {
cin>>n;
for(int i=1;i<=n;i++) scanf("%lld",&x),b.insert(x);
cout<<b.get_mx();
}
标签:logs 方程组 bool 相互 ... log 复杂 xor 一个
原文地址:http://www.cnblogs.com/foreverpiano/p/linear_basis.html