线性相关/线性基

线性基有啥用

例题:P3812 【模板】线性基

我们有些时候会遇到类似这样的问题:给定一组数字,求异或和最大值。

我们可以用线性基来解决这个问题。

怎么构建线性基呢

那么我们怎么考虑这个问题呢?

我们可以类比于向量。

在向量中,我们可以用单位向量表示某一个方向上的单位量。并且我们能用n个单位向量导出一个$n$维的空间。

同理对于异或空间也是可以线性基来导出的。

我们可以把一个长整型看成$64$维的向量,每个方向为$0$或$1$。

我们考虑一个数能导出怎样的一个单位向量呢?

我们发现如果是单位向量,那么这个向量除了当前这个方向上为$1$,其余都是$0$。

但是在这里我们可以放宽这个要求,我们要求高位上全为$0$,这一位为$1$。

如果前$k$维的单位向量都已经被成功导出,那么我们就可以完全地掌控前$k$维的空间了。

大致就是这个意思。

我们考虑插入一个数的操作。

我们从高位(维)向低位(维)遍历,如果我们发现当前第$i$位上为$1$,也就说明了这一个数对这个$i$维空间有影响。

我们判断一下,当前这个空间是否已经被成功导出了,如果已经被导出的话,我们就有办法消除这个影响,也就是异或上当前这个空间的单位向量。

如果没有被成功导出,那么我们最高就能影响到当前这个空间了,记录这个向量为当前空间的单位向量,结束循环。

有没有插入失败的情况呢?

有,就是当前这个向量能被完全消除影响,也就是说能被之前的向量导出的时候。

线性相关

给定一个线性空间,如果一个向量存在于这个空间中,就是说这个向量和这个空间线性相关。

这个线性空间是由一个向量集合导出的,具体见上面线性基的介绍。

例题:P3265 [JLOI2015]装备购买

常用模板

下面给一些常用的模板

插入元素

1 void Insert(ll a){
2     for(int i=63;i>=0;i--)if(a&(1LL<<i)){
3         if(num[i])a^=num[i];
4         else {
5             num[i]=a;
6             return;
7         }
8     }
9 }
View Code

查询某元素能否被表出

1 bool Inside(ll x){
2     if(!x)return 1;
3     for(int i=63;i>=0;i--)if(x&(1ll<<i)){
4         if(num[i])x^=num[i];
5         else return 0;
6         if(!x)return 1;
7     }
8     return 0;
9 }
View Code

查询能表出的最大值

1 ll query_maxn(){
2     ll now=0;
3     for(int i=63;i>=0;i--)
4         if((now^num[i])>now)
5             now^=num[i];
6     return now;
7 }
View Code

查询能表出的最小值

1 ll query_minn(){
2     for(int i=0;i<=63;i++)
3         if(num[i])return num[i];
4     return 0;
5 }
View Code

查询表出的第k小值

我们要查询第$k$小值,首先必须得让每一个单位向量能影响的范围独立,也就是说当前向量的选取对其他的向量没有影响。

之前我们保证了高位独立,这时候我们要重新建基,建一个新基,保证高位独立并且低位也独立。

并且按照独立团的个数进行重编号,那么第k大的数就相当于重编号后的$k$所对应的二进制数的异或和

 1 void rebuild(){
 2     for(int i=1;i<=63;i++)
 3         for(int j=i-1;j>=0;j--)
 4             if(num[i]&(1LL<<j))
 5                 num[i]^=num[j];
 6     for(int i=0;i<=63;i++)
 7         if(num[i])
 8             p[cnt++]=d[i];
 9 }
10 ll query_kth(ll k){
11     ll now=0;
12     if(k>=(1LL<<cnt))return -1;
13     for(int i=63;i>=0;i--)
14         if(k&(1LL<<i))
15             now^=p[i];
16     return now;
17 }
View Code

猜你喜欢

转载自www.cnblogs.com/onglublog/p/10047933.html