线性空间+线性基
yzh_Error404 · · 个人记录
向量:一行的矩阵或者一列的矩阵
线性空间:由一组向量通过线性组合能够表示的向量的集合
线性相关和线性无关:一组向量中,存在1个向量能够由其余向量线性组合得到,则称这组向量线性相关
线性空间的基底:一组线性无关的,数量最多的向量(极大线性无关的生成子集)
线性空间基底不是唯一的
线性空间的维度:一组基底的向量的个数
矩阵的秩:化成最简阶梯矩阵时,非零行向量或者非零列向量的个数
异或空间
由一组整数通过线性组合能够异或得到的整数集合
线性相关和线性无关:一组整数中,存在1个整数能够由其他整数异或得到,则称为线性相关
线性基:一组最大的线性无关的整数组合
一个异或空间的线性基的整数个数是相同的
线性基中的整数不可能异或得到0
线性基中的整数的最高位的位置互不相同
线性基的应用场景:
1.求一组整数异或得到的第k小数
2.求一个数是否能够被一组整数异或得到
普通方法:
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN=5005;
int a[MAXN];
int n,cnt,ans;
signed main()
{
int ans=0;
scanf("%lld",&n);
cnt=n;
for(register int i=1;i<=n;i++)
scanf("%lld",&a[i]);
for(register int i=1;i<=n;i++)
{
for(register int j=i+1;j<=n;j++)
if(a[j]>a[i])swap(a[i],a[j]);
if(!a[i])
{
cnt=i-1;
break;
}
for(register int j=63;j>=0;j--)
if(a[i]&((1ull)<<j))
{
for(register int k=1;k<=n;k++)
if(i!=k&&(a[k]&(1ull)<<j))
a[k]^=a[i];
break;
}
}
for(register int i=1;i<=cnt;i++)
ans=max(ans,ans^a[i]);
printf("%lld",ans);
return 0;
}
构造方法求线性基:
1.从a[1]开始,尝试将每个元素插入线性基的集合
2.从最高位向最低位枚举,若第j位上还没有1,但在x在第j位有1,则将x插入集合p[j],否则x^=p[j]
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN=65;
int p[MAXN]; //基底的集合
int n,x,ans;
inline void check(int x) //将x尝试插入基底的集合
{
for(register int i=63;i>=0;i--)
{
if(x>>i) //提取x最高位1所在的位置
{
if(p[i]==0) //如果第i位还没有任何一个向量有1
{
p[i]=x;
break;
}
else x=x^p[i];//如果第i位已经有1,则将x^p[i]得到新的x,再去继续找高位1
}
}
return;
}
signed main()
{
scanf("%lld",&n);
for(register int i=1;i<=n;i++)
{
scanf("%lld",&x);
check(x);
}
for(register int i=63;i>=0;i--)
ans=max(ans,ans^p[i]);
printf("%lld",ans);
return 0;
}