线性基
目录注:常用于异或
定义:
线性相关和线性无关
平面向量基本定理:平面上两个不共线向量可以表示出该平面上任意一个向量
这个定理可以拓展到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;
}
标签:基中,int,异或,线性相关,线性,向量
From: https://www.cnblogs.com/linghusama/p/17610071.html