[数论]线性基学习笔记
\(Q:\)这都是些什么东西?听起来就觉得很毒瘤难啊??
\(A:\)这就是一种反人类的工具。
先来下定义:
-
向量加法
对于两个向量\(a=(a_1,a_2,\dots,a_n),b=(b_1,b_2,\dots,b_n)\),有
\[c=a+b=(a_1+b_1,a_2+b_2,\dots,a_n+b_n) \] -
标量乘法
对于向量\(a=(a_1,a_2,\dots,a_n)\),常数\(b\),有
\[c=ab=(a_1b,a_2b,\dots,a_nb) \] -
线性空间
设有\(n\)个向量\(\{a_1,a_2,\dots,a_n\}\),若向量\(b=c_1a_1+c_2a_2+\dots+c_na_n\),其中\(c_1,c_2,\dots,c_n\)为常数,则\(b\)可以由\(a_1,a_2,\dots,a_n\)表出,称所有这样的\(b\)的集合为一个“线性空间”,\(a_1,a_2,\dots,a_n\)为此线性空间的生成子集。
-
线性相关
若对于向量集合\(\{a_1,a_2,\dots,a_n\}\),存在\(a_i\)能被除\(a_i\)以外的\(a_1\sim a_n\)表出,则称这些向量“线性相关”,不则称为“线性无关”。
-
基
基则是线性空间的线性无关生成子集,基的向量个数称为线性空间的维数。
-
秩
对于一个\(N\times M\)的矩阵,称矩阵的每一行为一个长度为\(M\)的行向量,所表示的线性空间的维数称为矩阵的秩(行秩)。同理可定义列向量和列秩。
\(Q:\)可以说人话吗?
嘛其实上面的东西用处不是很大,只是介绍一下正式一点。
举个例子\(.jpg\)
线性空间 \(\Rightarrow\) 平面直角坐标系
线性相关 \(\Rightarrow\) \((0,1,1)=(0,0,1)+(0,1,0)\)
基 \(\Rightarrow\) \((1,0,0),(0,1,0),(0,0,1)\)即为一组基底(\(x,y,z\)轴的单位)
秩 \(\Rightarrow\) \(3\)
那么对于一个矩阵进行消元,剩下的显然构成一组基底。
-
模板题。
-
如何构造线性基?
设线性基第\(i\)位对应的数为\(p_i\)。
对每个数\(a_j\)从高位向低查询,若有第\(k\)位,则将\(a_jxor\)上\(p_k\),否则插入并\(break\)。
显然,一个数要么插入线性基,要么能被其他数\(xor\)而成。
- 如何查询最值?
弹性的从高到低遍历每一位,若\(i\)位为\(0\)则\(xor\)上\(p_i\)。
正确性显然 因为每一位不会在后面被改变,所以为\(1\)是最优的。
\(So\ Easy...?\)
时间复杂度 \(O(nlog_2a)\)
空间复杂度 \(O(log_2a)\)
代码:
#include <cstdio>
int n;
long long a,p[55];//各基底
int main()
{
scanf("%d",&n);
while(n--)
{
scanf("%lld",&a);
for(int i=51;i>=0;--i)
if(a>>i&1)
{if(p[i])a^=p[i];//已有对应基底
else p[i]=a,i=0;}//插入,结束
}
long long Ans=0;
for(int i=51;i>=0;--i)
if(!(Ans>>i&1))
Ans^=p[i];//贪心求解
printf("%lld\n",Ans);
return 0;
}
\(Q:\)学了这个之后我们可以干什么呢?
\(A:\)我们可以切黑题 解决许多与\(xor\)有关的题目了。
以上。逃去刷题了