码迷,mamicode.com
首页 > 其他好文 > 详细

线性基小节

时间:2017-08-23 23:01:47      阅读:216      评论:0      收藏:0      [点我收藏+]

标签: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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!