高斯消元 & 线性基

本来说不写了,但还是写点吧

[update 2017-02-18]现在发现真的有好多需要思考的地方,网上很多代码感觉都是错误的,虽然题目通过了

[update 2017-02-19]加入线性基

[update 2017-03-31]完善内容,改用markdown


Gauss Elimination

高斯消元(Gaussian elimination)是求解线性方程组的一种算法,它也可用来求矩阵的秩,以及求可逆方阵的逆矩阵。

它通过逐步消除未知数来将原始线性系统转化为另一个更简单的等价的系统。

它的实质是通过初等行变化(Elementary row operations),将线性方程组的增广矩阵转化为行阶梯矩阵(row echelon form)。

概念

增广矩阵

  • 系数矩阵右面加上一列常数

矩阵的初等行变换

  • 交换两行
  • 给一行乘上一个非零数
  • 把一行的倍数加到另一行上

主元

  • 从1到n枚举变量作为主元(需要选择这个变量系数绝对值最大的行保证数值稳定性,异或方程、同余方程选非0就可以)

  • 和单纯形法类似,主元要写到等式的一边然后用这个方程替换其他方程中的主元,实现上是用矩阵的初等行变换做加减消元

自由元

  • 枚举到一个变量,如果剩下的行中这个变量的系数都为0,这个变量就是自由元。

  • 自由元存在说明有的方程是线性相关的,加减消元后有的方程就被消掉了。

  • 自由元的值一旦确定,其他变元的值就确定了

  • 自由元数目是一定的,就是消元结束后全0方程的数目(注意矛盾方程消元后常数项不为0)。

  • 自由元集合不一定,但只要枚举一个自由元集合的所有取值就可以得到整个方程组的所有变量取值啦。

关键元

  • 每一行的第一个非零元
  • 通常来讲这个第i行的关键元应该是第i个。否则说明前面及自己中有自由元。
  • 实现上记录pivot[i]为以变元i为关键元的方程在哪一行,也就是变元i用到了哪一行



解线性方程组

过程:

  • 消元,不断把系数矩阵变成\(REF\)(阶梯型矩阵)
  • 消元之后回代之前就可以进行无解和多解的判断
  • 唯一解形成上三角矩阵,回代即可

实现:

完整的判断多解和无解的版本请见POJ2947

bool Gauss(Matrix a, int n) {
for(int i=1; i<=n; i++) {
int r=i;
for(int j=i+1; j<=n; j++)
if(abs(a[j][i]) > abs(a[r][i])) r=j;
if(abs(a[r][i])<eps) return false;
if(r!=i) for(int j=1; j<=n+1; j++) swap(a[r][j], a[i][j]); for(int j=i+1; j<=n; j++) {
double t = a[j][i]/a[i][i];
for(int k=i; k<=n+1; k++) a[j][k] -= t*a[i][k];
}
}
for(int i=n; i>=1; i--) {
for(int j=n; j>i; j--) a[i][n+1] -= a[i][j]*a[j][n+1];
a[i][n+1] /= a[i][i];
}
return true;
}

解XOR方程组

过程

设N个未知数,M个方程,A为系数矩阵

\(now\)表示当前到了哪一行

$now\ =\ 1 $

\(for\ i\ =\ 1\ to\ N\)

  若存在\(j\ \ge\ now\)使得\(A_{j\ ,\ i}\)为\(1\)则

    交换第\(j\)行与第\(now\)行

    用第\(now\)行对之后的行进行消元

    \(now\ +=\ 1\)

  否则第\(i\)个变量是自由变量,\(now\)不变

实现

可以使用bitset压位+高斯约当消元

高斯约当消元是选主元之后将主元化为1(xor方程不需要),然后枚举除主元所在行之外所有行消元,可以发现一个过程之后主元所在列就是单位矩阵(对角矩阵)的形式,所以最后不用回代。

void Gauss(bitset<N> a[N], int n) {
now=1;
for(int i=1; i<=n; i++) {
int j=now;
while(j<=n && !a[j][i]) j++;
if(j==n+1) continue;
if(j!=now) swap(a[now], a[j]);
for(int k=1; k<=n; k++)
if(k!=now && a[k][i]) a[k]^=a[now];
now++;
}
now--;
}



解的判断

无解

  • 存在矛盾方程,消元后系数全为\(0\),常数项不为\(0\)

多解

  • 出现了\(S\)个自由元,这些变量可任意取值从而确定其余变量的值\(2^S\)组解
  • 实现上,now<n说明出现自由元,并且自由元所在方程一定在最后几行。求最优解需要枚举自由元的取值然后回代

唯一解

  • 无自由元,即now=n,形成上三角矩阵

对于高斯约当消元

系数矩阵变成了对角矩阵

如果存在自由元,那么大约张这样

O....O

........#...O

...................O

空行

# 位置是一个自由元

这时候也需要枚举自由元的取值然后回代


求矩阵的逆

这里说一种方法,对A进行高斯约当消元,右面的常数列换成单位矩阵。校园后,左面变成了单位矩阵,右面就是\(A^{-1}\)

Matrix inverse(Matrix a) {
Matrix c; c.im();
for(int i=1; i<=n; i++) {
int r;
for(r=i; r<=n; r++) if(a[r][i]) break;
// r != n+1
if(r!=i) for(int j=1; j<=n; j++)
swap(a[i][j], a[r][j]), swap(c[i][j], c[r][j]);
ll inv = Pow(a[i][i], P-2);
for(int j=1; j<=n; j++)
a[i][j] = a[i][j]*inv%P, c[i][j] = c[i][j]*inv%P;
for(int k=1; k<=n; k++) if(k!=i) {
ll t = a[k][i]%P;
for(int j=1; j<=n; j++)
mod(a[k][j] -= a[i][j]*t%P), mod(c[k][j] -= c[i][j]*t%P);
}
}
return c;
}

线性基

概念

线性空间:

设\(V\)是一个向量集合

\(\forall a,b\ \in V\quad a+b \in V\)

\(\forall a\in V,\ k \in F\quad ka\in V\)

线性组合:

线性空间\(V\)的子集\(S=\{ v_1,v_2,...,v_n \}\),对于一个\(V\)中的元素\(v\),存在一组系数使得

\[v=a_1v_1+a_2v_2+...+a_nv_n
\]

那么\(v\)是\(S\)的一个线性组合

线性相关:

线性空间\(V\)的子集\(S=\{ v_1,v_2,...,v_n \}\),如果有一组系数使得

\(a_1v_1+a_2v_2+...+a_nv_n=0\)

则称S是线性相关的

也就是说\(S\)中的某个向量能被自己所表示出来


线性基:

和小新讲的向量的基底好像啊(就是一个东西吧)

\(V\)中的任意一个向量都能唯一的表示成\(S\)中向量的线性组合,那么\(S\)是\(V\)的一组基

线性基是满足线性无关的极大子集

线性基中元素的个数(基数)一定,就是线性空间的维度

任一线性无关组的子集线性无关

我们可以用一组向量\(S\)(不一定线性无关)来构造线性空间,称为\(span(S)\)

矩阵的秩

矩阵可以看成一个向量组,线性基对应着矩阵的秩

矩阵的行秩等于列秩

\(行列式不为0 \Leftrightarrow 满秩 \Leftrightarrow 向量线性无关\)

可以使用高斯消元求矩阵(横向量组)的秩(线性基)


拟阵

类似最小生成树

线性无关子集构成一个拟阵,可以用贪心求最大权线性基


异或问题

把每个二进制位看成一个维度,每个整数就是一个向量,向量之间的运算是异或,一个整数的集合就是一个线性空间

插入

用p[i]保存线性基里第i个数位为1的向量(数字)(类似于高斯消元里的每个主元用到哪一行)

待插入x,从高位到低位枚举x为1的二进制位i,如果有p[i]了那么异或p[i]消去x这一位的1,如果没有p[i]那么p[i]=x并推出

如果x最后不是0说明插入成功,否则说明x和已经插入的数字线性相关

注意插入结束后,保证数字p[i]在第i位为1且之后的数字第i位都不是1,不保证在p[i]之前插入的数字第i位不是1,所以在这种线性基上求最大值不能直接异或上要取max

这样可以配合贪心求最大权线性基

合并

将一个全部插入另一个就好了

构造

异或高斯消元后形成对角矩阵,每一位只有一个数字是1

这时候有now个位可以是1,最多有\(2^{now}\)种取值,第i行a[i]保存了第i大的可以是1的二进制位的




利用构造后的线性基可以求线性空间的最大值,最小值,k小值

  • 异或所有a[i]
  • a[now],严格次大值就是a[i]^a[now]
  • 对k二进制拆分,第i位为1异或上则异或上a[now-i]

高斯消元 & 线性基【学习笔记】的更多相关文章

  1. 洛谷P3389 高斯消元 / 高斯消元+线性基学习笔记

    高斯消元 其实开始只是想搞下线性基,,,后来发现线性基和高斯消元的关系挺密切就一块儿在这儿写了好了QwQ 先港高斯消元趴? 这个算法并不难理解啊?就会矩阵运算就过去了鸭,,, 算了都专门为此写个题解还 ...

  2. HDU 3949:XOR(高斯消元+线性基)

    题目链接 题意 给出n个数,问这些数的某些数xor后第k小的是谁. 思路 高斯消元求线性基. 学习地址 把每个数都拆成二进制,然后进行高斯消元,如果这个数字这一位(列)有1,那么让其他数都去异或它,消 ...

  3. BZOJ 2844 albus就是要第一个出场 ——高斯消元 线性基

    [题目分析] 高斯消元求线性基. 题目本身不难,但是两种维护线性基的方法引起了我的思考. void gauss(){ k=n; F(i,1,n){ F(j,i+1,n) if (a[j]>a[i ...

  4. BZOJ 4004 JLOI2015 装备购买 高斯消元+线性基

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4004 Description 脸哥最近在玩一款神奇的游戏,这个游戏里有 n 件装备,每件装 ...

  5. 【BZOJ-4269】再见Xor 高斯消元 + 线性基

    4269: 再见Xor Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 131  Solved: 81[Submit][Status][Discuss] ...

  6. BZOJ 4269: 再见Xor [高斯消元 线性基]

    4269: 再见Xor Description 给定N个数,你可以在这些数中任意选一些数出来,每个数可以选任意多次,试求出你能选出的数的异或和的最大值和严格次大值. 我太愚蠢了连数组开小了以及$2^{ ...

  7. BZOJ 2844 高斯消元 线性基

    思路: //By SiriusRen #include <cstdio> #include <cstring> #include <algorithm> using ...

  8. HDU 3949 XOR(高斯消元搞基)

    HDU 3949 XOR pid=3949" target="_blank" style="">题目链接 题意:给定一些数字,问任取几个异或值第 ...

  9. [JLOI2015]装备购买 题解 / 实数线性基学习笔记

    题目链接 看这道题之前,以为线性基只是支持异或的操作... 那么,我认为这道题体现出了线性基的本质: 就是说如何用最小的一个集合去表示所有出现的装备. 我们假设已经会使用线性基了,那么对于这道题该怎么 ...

随机推荐

  1. A * B Problem Plus(fft)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1402 hdu_1402:A * B Problem Plus Time Limit: 2000/100 ...

  2. SQL强化(三) 自定义函数

    ---恢复内容开始--- Oracle中我们可以通过自定义函数去做一些逻辑判断,这样可以减少查询语句,提高开发效率 create  -- 创建自定义函数 or replace -- 有同名函数就替换, ...

  3. 二维数组模拟实现酒店管理系统-java

    业务分析 1.需要一个房间类,包含房间的属性,比如房间编号.房间类型.是否占用. 2.需要一个旅馆类,旅馆有房间,提供的方法需要有 预订房间.打印房间信息.初始化房间.退房. 3.测试类,测试预订房间 ...

  4. MYSQL 数据库导入导出命令

    在不同操作系统或MySQL版本情况下,直接拷贝文件的方法可能会有不兼容的情况发生.所以一般推荐用SQL脚本形式导入.下面分别介绍两种方法. MySQL命令行导出数据库 1,进入MySQL目录下的bin ...

  5. ntp 时钟同步

    注意: 如果你无法和外部网络的时钟同步,请检查UDP端口时候被封.

  6. python装饰器的用法

    def logger(func):    def inner(*args, **kwargs): #1         print "Arguments were: %s, %s" ...

  7. C#、Java之比较

    很多人说C#是微软用来和Java抗衡的武器,因为二者在很大程度上有着惊人的相似,尽管如此,两者不同的地方也很多,所谓"于细微处见差异".那么两者的相似和区别都在什么地方呢?我们从今 ...

  8. webpack从0开始---(二)

    直接使用webpack进行打包 安装css loader,style loader(用来处理打包css文件) 命令行输入npm install css-loader style-loader --sa ...

  9. mavean的依赖传递和排除依赖

    三个mavean项目 A  .B. C 如果B依赖A(A先执行clean package命令) 那么B得pom.xml文件里面就写 <dependency> <groupId> ...

  10. jsp中 scope="application" 表示

    jsp中 <jsp:useBean id="countbean" scope="application" class="count.counte ...