OI中常見的線性代數矩陣問題
阿新 • • 發佈:2018-12-29
對於一個 的矩陣 ,我們這樣定義:
struct matrix{
int n,m;
double a[N][N];
}A;
回憶初中學的多元一次方程(線性方程),我們可以把它當做一個矩陣,然後等號的後面為 的增廣矩陣。
我們解答的過程,就是用方程之間的加減,或者乘一個常數,來消去一些未知數,直到可以直接解出答案。這個消元過程,就是高斯消元。
變換到矩陣上面,就是通過一些行與行之間的加減,或者乘一個常數,來使得一些位置的值變為 。
我們一般會畫成下面兩種形態:
- 行階梯式
程式碼如下,複雜度
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];
}
}
}
- 行最簡式
程式碼如下,在化成行階梯式之後,再化成行最簡式,複雜度
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];
}
}
- 矩陣的秩
矩陣的秩是A的線性獨立的縱(橫)列的極大數目,感性地理解,就是線上性方程裡的非自由元數目,也就是有用的為多少,我們可以在高斯消元的同時,來求矩陣的秩。
也就是統計行階梯式的對角線上,不為 的數目。
- 行列式的值
行列式雖然與矩陣不同,但是也可以用矩陣表示,暴力求行列式的值複雜度太高,但是我們可以高斯消元過後再求。
就是行階梯式的對角線的乘積。
那麼對於矩陣之間的乘法 ,我們這樣定義: