高斯消元法

来源:互联网 发布:超时空要塞f知乎 编辑:程序博客网 时间:2024/04/30 00:47
高斯消元法是一种用于解线性方程组的算法。所谓线性方程组,就是一次方程组。或者说,就是可以用以描述一个空间中若干条线的方程组。规范化地表示,就是:

a11x1+a12x2+......+a1mxm=c1......an1x1+an2x2+......+anmxm=cn

容易看出,这样的线性方程组其实是可以和矩阵扯上关系的。所谓矩阵,就是形如这样的一个数字方阵:
a11am1a1namn

同时,我们顺便定义一下矩阵乘法。矩阵乘法要求参与运算的两个矩阵中的一个的行数等于另一个的列数。下面是定义。对于某两个矩阵AB,那么有(A×B)ij=k=0nAikBkj
从这里得到启发,可以定义系数矩阵、未知数矩阵以及等式右边的常数矩阵AxC。那么根据矩阵乘法,我们可以将这一共n个等式极为简单地描述为一个等式,即Ax=C。这样,我们就能够发现,其实矩阵的效用非常大,像一个n×n的矩阵的效用甚至可以很简洁地代替n个标量等式!
好吧,回到正题。如果我们现在有AC两个矩阵(因为其实未知数矩阵的用处没有那么大),那么怎样能够求出相对应的各个未知数的值呢?那么这就是高斯消元法的用处所在了。
考虑我们在现实中是怎样解方程的?有一种较为通用的解法,即加减消元法。考虑系数矩阵中的两行,我们要消掉这两行的第一个变量,比如说这两行:
a11am1a1namn

我们先假设这些系数都是整数(因为大多数情况下,完全都可以变成整数)。那么根据我们加减消元的方法,我们可以给这第m行全部都乘上一个a11am1,换句话也就是
a11a11a1namna11am1

解出来之后,还有一个回代的过程。即考虑下面的这样的一种消元之后的上三角矩阵:
a11000a1namn

然后直接回代即可。从下往上循环,每一次可以确定一个变量,然后将其上面的所有行给代进去,将相应的系数变成0,方程式右边的常数项也相应地减去相应的量。
这就是高斯消元法。其的时间复杂度其实是相当好估计的。每一次先选择两行,再将这两行开始消元,于是每一次消元需要枚举每一个矩阵中的变量,所以就是O(n2m),是立方级的。
另外,为了提高数值的稳定性(即提高精度),我们一般来说采用一种主元法。考虑到我们上面那里是用相应的项乘上一个a11am1,那么为了提高精度,应当使得am1尽量小而a11尽量大。所以,为了提高精度,我们应该选取一个使得a11绝对值最大的行,这样便可以提高精度。
下面我们来考虑一种较为特殊的情况。如果我们消元时乘上的不是分数,而是另外的什么东西,使得最终能够求出整数解?答案是肯定的。先考虑最简单的情况,我们还以上面的两行举例:
a11am1a1namn

消元要使得这两行中某两个变量一致,那么最简单的方法就是互乘:
a11am1a11am1a1nam1a11amn

但是这样很容易爆掉,所以可以适当地加上一个优化,这个优化有时并不十分有效,但是一般来说是很好的。这个优化就是使得矩阵变成这样:
a11am1gcd(a11,am1)a11gcd(a11,am1)am1a1nam1gcd(a11,am1)a11gcd(a11,am1)amn

虽然看上去很壮观(挺大的……)但是实际上还是很简单的(就加了一个gcd罢了)。
下面,我们要讨论一个另外相对较难的东西:模方程。模方程其实就是形如下面式子的这类方程:
a11x1+a12x2++a1nanc1(modd1)am1x1+am2x2++amnancm(moddm)

理论上来说,这类方程实际上和普通的方程没有什么区别,因为和普通的方程一样,我们也可以用高斯消元法。怎么用呢?我们只需要乘上模方程的“分数”即可。我们先来看看,模方程中的分数是什么。
考虑通常的分数,我们有ab=a×1b。同时,倒数还有另一种关于负数次方的写法,所以也可以写成是ab=ab1考虑模意义下的倒数,叫做“逆元”(相信大多数人已经知道了),而逆元满足a×a11(modm)。这和倒数的意义相当,但是模意义下的乘法逆元是在不同的一个数字体系中的。从上面的式子,我们可以得到
a×a1=mk+1

进而有
a×a1mk=1

于是,考虑这个二元一次不定方程,其中k是任意正整数,而a1是我们要知道的量(即逆元)。容易想到用扩展GCD来求,这里就不多叙述了。
实际的过程如果用这样的解法的话应该是和高斯消元法差不多的,感觉上并不难。
总结一下,用高斯消元法解决的问题大多数都是和方程有关的,这和信息学的一个抽象化的思路很有关联。高斯消元法实际上是一个相当重要的内容,因为本身可以解决许多的题目,而且和单纯形法也有很大的关联。

1 0
原创粉丝点击