1. 程式人生 > >OI中常見的線性代數矩陣問題

OI中常見的線性代數矩陣問題

         \ \ \ \ \ \ \, 對於一個 n × m

n\times m 的矩陣 A A ,我們這樣定義:

A = [

a ( 1 , 1
)
a ( 1 , 2 ) a ( 1 , n )
a ( 2 , 1 ) a ( 2 , 2 ) a ( 2 , n ) a ( m , 1 ) a ( m , 2 ) a ( m , n )
] A=\begin{bmatrix} a_{(1,1)} & a_{(1,2)} &\cdots &a_{(1,n)} \\ a_{(2,1)}& a_{(2,2)} &\cdots &a_{(2,n)} \\\vdots &\vdots &\ddots &\vdots\\ a_{(m,1)}& a_{(m,2)} &\cdots &a_{(m,n)} \end{bmatrix}

struct matrix{	
	int n,m;
	double a[N][N];
}A;
  • 高斯消元

         \ \ \ \ \ \ \, 回憶初中學的多元一次方程(線性方程),我們可以把它當做一個矩陣,然後等號的後面為 n × 1 n\times 1 的增廣矩陣。

         \ \ \ \ \ \ \, 我們解答的過程,就是用方程之間的加減,或者乘一個常數,來消去一些未知數,直到可以直接解出答案。這個消元過程,就是高斯消元。

         \ \ \ \ \ \ \, 變換到矩陣上面,就是通過一些行與行之間的加減,或者乘一個常數,來使得一些位置的值變為 0 0

         \ \ \ \ \ \ \, 我們一般會畫成下面兩種形態:

  1. 行階梯式

[ 0 0 0 ] \begin{bmatrix} * & * &* \\ 0& * &* \\0& 0 &* \end{bmatrix}

         \ \ \ \ \ \ \, 程式碼如下,複雜度 O ( n 3 ) O(n^3)

void Gauss(matrix &A){
	for(int i=1;i<=A.n;i++){
		for(int j=i;j<=A.m;j++)
		if(fabs(A.a[j][i])){swap(A.a[j],A.a[i]);break;}
		for(int j=i+1;j<=A.m;j++){
		if(fabs(A.a[i][i])<eps)continue;
		double f=A.a[j][i]/A.a[i][i];
		for(int k=i;k<=A.n;k++)A.a[j][k]-=f*A.a[i][k];
		}
	}
}
  1. 行最簡式

[ 0 0 0 0 0 0 ] \begin{bmatrix} * &amp; 0 &amp;0 \\ 0&amp; * &amp;0 \\0&amp; 0 &amp;*\end{bmatrix}

       &ThinSpace; \ \ \ \ \ \ \, 程式碼如下,在化成行階梯式之後,再化成行最簡式,複雜度 O ( n 3 ) O(n^3)

void Gauss(matrix &A){
	for(int i=1;i<=A.n;i++){
 		for(int j=i;j<=A.m;j++)
 		if(fabs(A.a[j][i])){swap(A.a[j],A.a[i]);break;}
 		for(int j=i+1;j<=A.m;j++){
 			if(fabs(A.a[i][i])<eps)continue;
 			double f=A.a[j][i]/A.a[i][i];
      for(int k=i;k<=A.n;k++)A.a[j][k]-=f*A.a[i][k];
		}
	}
	for(int i=A.n;i>=1;i--)
 	for(int j=i-1;j>=1;j--){
 		if(fabs(A.a[j][i])<eps)continue;
 		double f=-A.a[i][i]/A.a[j][i];
    for(int k=j;k<=A.n;k++)
    (A.a[j][k]*=f)+=A.a[i][k];
	}
}

  • 矩陣的秩和行列式的值

  1. 矩陣的秩

       &ThinSpace; \ \ \ \ \ \ \, 矩陣的秩是A的線性獨立的縱(橫)列的極大數目,感性地理解,就是線上性方程裡的非自由元數目,也就是有用的為多少,我們可以在高斯消元的同時,來求矩陣的秩。

        &ThinSpace; \ \ \ \ \ \ \ \, 也就是統計行階梯式的對角線上,不為 0 0 的數目。

  1. 行列式的值

       &ThinSpace; \ \ \ \ \ \ \, 行列式雖然與矩陣不同,但是也可以用矩陣表示,暴力求行列式的值複雜度太高,但是我們可以高斯消元過後再求。

       &ThinSpace; \ \ \ \ \ \ \, 就是行階梯式的對角線的乘積。


  • 矩陣乘法

       &ThinSpace; \ \ \ \ \ \ \, 那麼對於矩陣之間的乘法 B × A B\times A ,我們這樣定義: