线性基小节
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线性基小节相关的知识,希望对你有一定的参考价值。
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(); }
以上是关于线性基小节的主要内容,如果未能解决你的问题,请参考以下文章