1. 程式人生 > 實用技巧 >複習筆記——線性代數

複習筆記——線性代數

高斯消元

還是注意解的判斷:
1.出現0=0:無陣列解
2.出現0=1:無解
3.else:唯一解

實數版

typedef double db;
typedef db Mat[N][N];

bool gauss(Mat A,int n){
	for(int i=1;i<=n;i++){
		int r=i;
		for(int j=i+1;j<=n;j++)
			if(A[j][i]>A[r][i]) r=j;
		for(int j=i;j<=n+1;j++) swap(A[i][j],A[r][j]);
		if(fabs(A[i][i])<eps) continue;
		for(int j=i+1;j<=n;j++){
			db t=A[j][i]/A[i][i];
			for(int k=i;k<=n+1;k++) 
				A[j][k]-=A[i][k]*t;
		}
	}
	for(int i=n;i>0;i--){
		for(int j=i+1;j<=n;j++)
			A[i][n+1]-=A[i][j]*A[j][j];
		if(A[i][i]==0) return false; //if A[i][n+1]=0:oo solutions else:no solution
		A[i][i]=A[i][n+1]/A[i][i];
	}
	return true;
}

對質數取模版

把實數版的所有除法換位逆元即可

對合數取模版

不是所有數都對合數有逆元,因此在消元時無法直接乘上逆元;但消元的目的是將一方消為0,聯想到輾轉相除求gcd時最終也是將某個數變為了0,於是可以輾轉相除消元。
然而代入求值時可能出bug,但在求行列式等操作中還是很可能出現的。放個消成上三角矩陣的程式碼。

bool Gauss(Mat A,int n){
	for(int i=1;i<=n;i++){
		int r=i;
		for(int j=i+1;j<=n;j++)
			if(A[j][i]>A[r][i]) r=j;
		for(int j=i;j<=n+1;j++) swap(A[i][j],A[r][j]);
		if(!A[i][i]) return false;
		
		for(int j=i+1;j<=n;j++){//make A[j][i]=0
			while(A[j][i]){ //b
				int t=A[i][i]/A[j][i]; //(a,b)->(b,a%b)=(b,a-(a/b)*b)
				for(int k=i;k<=n+1;k++){
					A[i][k]=Minus(A[i][k],1ll*A[i][k]*t%P);
					swap(A[i][k],A[j][k]);
				}
			}
		}
	}
	return true;
}

線性基

在異或空間中常用的性質:一個線性空間中,極大線性無關子集的大小的一定的。

ll c[N];
void insert(ll x){
	for(int i=50;i>=0;i--)
		if((x>>i)&1){
			if(!c[i]) { c[i]=x; return; }
			x^=c[i];
		}
}

矩陣求逆

矩陣 \(A\) 有逆的充要條件是:\(A\) 可通過線性變換變為單位矩陣。
推導: 若矩陣 \(B\) 滿足 \(B\times [A|E]=[E|B]\)\(E\) 為單位矩陣),則 $ B \times A =E$,即 \(B=A^{-1}\)


求法:對 \([A|E]\) 高斯消元,消成 \([E|B]\) 的形式(即將 \(A\) 消成 \(E\)),就得到 \(B\) 了。

\(trick\) :懶得迴帶?那就把所有除 \(A[i][i]\) 以外的 \(A[j][i]\) 都一次性消為0(操作上改下迴圈的起始位置即可)

bool Gauss_inv(Mat A,int n){
	for(int i=1;i<=n;i++){
		int r=i;
		for(int j=i+1;j<=n;j++)
			if(A[j][i]>A[r][i]) r=j;
		for(int j=i;j<=2*n;j++) swap(A[i][j],A[r][j]);
		if(!A[i][i]) return false;
		int Inv=Pow_mod(A[i][i],P-2);
		for(int j=1;j<=n;j++) { //trick: from 1->n all delete
			if(j==i) continue;
			int t=1ll*A[j][i]*Inv%P;
			if(!t) continue;
			for(int k=i;k<=n*2;k++)
				A[j][k]=Minus(A[j][k],1ll*t*A[i][k]%P);
		}
	}
	for(int i=1;i<=n;i++){
		int Inv=Pow_mod(A[i][i],P-2);
		for(int j=n+1;j<=n*2;j++) 
			A[i][j]=1ll*A[i][j]*Inv%P;
		A[i][i]=1;
	}
	return true;
}

矩陣乘法 & 矩陣快速冪

太簡單了就不說了吧。


矩陣行列式

終於知道定義了,但懶得寫了。
一些性質:
1.將某一行 \(\times k\) 後加到另一行,行列式不變
2.交換某兩行,行列式 \(\times = -1\)
3.某一行 \(\times k\),行列式 \(\times = k\)
4.把矩陣消成上三角or下三角矩陣後,行列式=對角線上所有數的乘積

程式碼中要注意的就是交換兩行後記得 \(ret*=-1\)