最后冲刺!!!|

铃狐sama

园龄:1年11个月粉丝:5关注:5

线性基(异或)

线性基


注:常用于异或

定义:

线性相关和线性无关

平面向量基本定理:平面上两个不共线向量可以表示出该平面上任意一个向量
这个定理可以拓展到n维
有了这个,就能轻松理解下面的概念了。
线性相关:假设我有k个向量,如果这k个向量中,任意一个向量能被其他向量表示出来,那么就线性相关。
线性无关:k个向量中,任意一个无法用其他的来表示,那么就线性无关。、

基:在V中找一个最大的线性无关向量组,其大小称为V的维数,记作dimV。这组向量也叫做V的一组基。
换句话说,利用一个基中的向量,可以表示出V中的任意向量

线性基的维护

基本操作

相当于动态地维护行(简化)阶梯形矩阵
维护的时候想象向量组排成一个阶梯矩阵
核心是每一个位都关联一个向量,这个向量的最高位恰好是该位
比方说现在插入一个向量x,先看最高位是否在已有的线性基中出现过,如果出现过一个y,x和y有相同的最高位,
那么x^=y,x的最高位就变低了,继续在线性基中找,直到找不到有相同的最高位,
那么让x的最高位和x关联,如果x被异或到0了就说明x能被线性基中的元素线性表出

在线段树分治中的维护

线性基不好删除,对于只能加不能删的我们可以考虑如何撤销(也好撤销),然后线段树分治

线性基的应用(代码模板在此)

https://www.luogu.com.cn/problem/P3812

分析:

最大异或和,给定一个集合,找一个子集使得异或和最大
把数写成二进制,拆成向量
异或相当于mod2加法,维护模2意义下的线性基
从高位起,依次考虑线性基(阶梯矩阵)的每一个分量,若异或上能让答案更大就异或上。

代码:

注释:代码里面的cmp其实并不需要

#include<bits/stdc++.h>
#define int long long
using namespace std;
int p[64];
int a[105];
bool cmp(int x,int y){
	return x>y;
}
void insert(int x){
	for(int i=61;i>=0;i--){
		if(((1<<i)>x)||(!(x>>i))){
			continue;
		}
		if(!p[i]){
			p[i]=x;
			break;
		}
		x^=p[i];
	}
}
signed main(){
	ios::sync_with_stdio(false);
	int n;
	cin >> n;
	for(int i=1;i<=n;i++){
		cin >> a[i];
	}
	sort(a+1,a+1+n,cmp);
	for(int i=1;i<=n;i++){
		insert(a[i]);
	}
	int ans = 0;
  	for (int i = 61; ~i; --i) {
    	ans=max(ans, ans^p[i]);
  	}
  	cout<<ans;
  	return 0;
	
}


本文作者:linghusama

本文链接:https://www.cnblogs.com/linghusama/p/17610071.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   铃狐sama  阅读(58)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起