线性基小节

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();
}

 

以上是关于线性基小节的主要内容,如果未能解决你的问题,请参考以下文章

如何通过单击片段内的线性布局从片段类开始新活动?下面是我的代码,但这不起作用

bzoj 4269 再见Xor 线性基

Codeforces 1100F(线性基+贪心)

线性基 刷题记录

P3857 [TJOI2008]彩灯(线性基)

线性基讲解