代數余子式和伴隨矩陣


入門之后的一篇文章。

啊啊啊這玩意學了我一整天!這什么菜狗啊!

一、代數余子式

\(n\) 階方陣 \(A=(a_{i,j})\) 中,刪去第 \(i\) 行和第 \(j\) 列后所留下的方陣的行列式稱為 \(a_{i,j}\)余子式 \(M_{i,j}\),而 \(a_{i,j}\) 的代數余子式為 \(A_{i,j}=(-1)^{i+j}M_{i,j}.\)

代數余子式可以用來算行列式:

\[\det(A)=\sum_{c=1}^n a_{r,c}A_{r,c} \]

二、伴隨矩陣

(一)、定義

真不是因為我懶,主要是這個矩陣我不太會用 markdown 畫出來。懶得搜還不是懶

(二)、性質及求解方法

首先我們用高斯消元計算 \(A\) 的 rank,然后分情況討論。

1.rank(A)=n

有這樣一個公式:\(AA^{*}=|A|I\),那么可得 \(A^{*}=|A|A^{-1}\)

我們試着感性證明一波 \(AA^{*}=|A|I\)

首先我們根據左行乘右列,當左邊的行序數和右邊的列序數相等時,由一、代數余子式中的公式可知算出來就是 \(|A|\)

那么不相等的時候呢?相當於算的是:\(\sum_{c=1}^n a_{i,c}A_{r,c}(i\not=r)\),相當於計算將最初的方陣 \(A\) 的第 \(i\) 行換為第 \(r\) 行的方陣后,計算它的行列式,由於有兩行相等,\(A\) 不滿秩,行列式為 0,所以上面那個式子算出來就是 0。

2.rank(A)<n-1

顯然此時刪掉一行一列之后仍然不滿秩,所以 \(A^*=O,\operatorname{rank}(A^{*})=0\)

3.rank(A)=n-1

麻煩的來了。

首先由 \(\operatorname{rank}(A)=n-1\) 可知 \(\dim\ker(A)=1\)。於是存在非零行向量和列向量 \(p,q\) 使得 \(pA=0,Aq=0\)\(p,q\) 可以高斯消元求出。(這里有點類似於高中數學求平面的法向量)

由於行列最后得出的結論類似,所以我們這里只以列為例講解。

\(Aq=0,\dim\ker(A)=1,\operatorname{rank}(A^*)=1\)

可得 \(A*\) 的每一行都是第一行的若干倍數,又因為 \(\operatorname{rank}(A)<n\),所以 \(|A|=0\)

\(|A|=a_{1,1}A_{1,1}+a_{1,2}A_{1,2}+...+a_{1,n}A_{1,n}=0\)

\(a_{1,1}q_1+a_{1,2}q_2+...+a_{1,n}q_n=0\)

\(\dim\ker(A)=1\) 可知 \(\frac{A_{1,1}}{q_1}=\frac{A_{1,2}}{q_2}=...=\frac{A_{1,n}}{q_n}\)。(當然這里如果有0就不能寫成分式形式,但是為了美觀還是這么寫)

那么行的結論同理可得:\(\frac{A_{1,1}}{p_1}=\frac{A_{2,1}}{p_2}=...=\frac{A_{n,1}}{p_n}\)

所以為了求出所有的 \(A_{i,j}\),我們需要找到 \(r,c\) 使得 \(p_r,q_c\not=0\),那么可得 \(A_{i,j}=\frac{p_{i}q_{j}}{p_rq_{c}}A_{r,c}\),至於 \(A_{r,c}\) 直接暴力 \(O(n^3)\) 求即可。

(三)、例題

題目大意:求方陣的余子式。

Vjudge

OpenJudge

差點就拿DDG的代碼開拍了
//12252024832524
#include <bits/stdc++.h>
#define TT template<typename T>
using namespace std; 

typedef long long LL;
const int MAXN = 200;
const int MOD = 998244353;
int n;

LL Read()
{
	LL x = 0,f = 1;char c = getchar();
	while(c > '9' || c < '0'){if(c == '-')f = -1;c = getchar();}
	while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
	return x * f;
}
TT void Put1(T x)
{
	if(x > 9) Put1(x/10);
	putchar(x%10^48);
}
TT void Put(T x,char c = -1)
{
	if(x < 0) putchar('-'),x = -x;
	Put1(x); if(c >= 0) putchar(c);
}
TT T Max(T x,T y){return x > y ? x : y;}
TT T Min(T x,T y){return x < y ? x : y;}
TT T Abs(T x){return x < 0 ? -x : x;}

int qpow(int x,int y)
{
	int ret = 1;
	while(y){if(y & 1) ret = 1ll * ret * x % MOD;x = 1ll * x * x % MOD;y >>= 1;}
	return ret;
}

int tmp[MAXN][MAXN];
struct Matrix
{
	int n,a[MAXN][MAXN];
	
	Matrix(){memset(a,0,sizeof(a));}
	
	void Get(int x){n = x;for(int i = 0;i < n;++ i) for(int j = 0;j < n;++ j) a[i][j] = Read();}
	void print(){for(int i = 0;i < n;++ i)for(int j = 0;j < n;++ j) Put(a[i][j],j == (n-1) ? '\n' : ' ');}
	void Add(int r1,int r2,int k){for(int i = 0;i < n;++ i) a[r2][i] = (a[r2][i] + 1ll * a[r1][i] * k) % MOD;}
	void Mul(int r,int k){for(int i = 0;i < n;++ i) a[r][i] = 1ll * a[r][i] * k % MOD;}
	void Mul(int k){for(int i = 0;i < n;++ i) for(int j = 0;j < n;++ j) a[i][j] = 1ll * a[i][j] * k % MOD;}
	void Trans(){for(int i = 0;i < n;++ i) for(int j = i;j < n;++ j) swap(a[i][j],a[j][i]);}
	Matrix TransNd(){Matrix ret;ret.n = n;for(int i = 0;i < n;++ i) for(int j = 0;j < n;++ j) ret.a[i][j] = a[j][i];return ret;}
	
	int Det(bool ri = 1)//whether ruin the previous one
	{
		int ret = 1;
		if(!ri) for(int i = 0;i < n;++ i) for(int j = 0;j < n;++ j) tmp[i][j] = a[i][j];
		for(int i = 0;i < n;++ i)
		{
			if(!a[i][i]) for(int j = i+1;j < n;++ j) if(a[j][i]) {ret = -ret;swap(a[i],a[j]);break;}
			if(!a[i][i]) {ret = 0;break;}
			for(int j = i+1;j < n;++ j)
				if(a[j][i])
				{
					int mul = 1ll * a[j][i] * qpow(a[i][i],MOD-2) % MOD;
					for(int k = i;k < n;++ k) a[j][k] = ((a[j][k] - 1ll * mul * a[i][k]) % MOD + MOD) % MOD;
				}
			ret = 1ll * ret * a[i][i] % MOD;
		}
		if(!ri) for(int i = 0;i < n;++ i) for(int j = 0;j < n;++ j) a[i][j] = tmp[i][j];
		return (ret+MOD)%MOD;
	}
	
	int Rank(bool ri = 1)
	{
		int ret = n;
		if(!ri) for(int i = 0;i < n;++ i) for(int j = 0;j < n;++ j) tmp[i][j] = a[i][j];
		for(int i = 0;i < n;++ i)
		{
			if(!a[i][i]) for(int j = i+1;j < n;++ j) if(a[j][i]) {swap(a[i],a[j]);break;}
			if(!a[i][i]) {--ret;continue;}
			for(int j = i+1;j < n;++ j)
				if(a[j][i])
				{
					int mul = 1ll * a[j][i] * qpow(a[i][i],MOD-2) % MOD;
					for(int k = i;k < n;++ k) a[j][k] = ((a[j][k] - 1ll * mul * a[i][k]) % MOD + MOD) % MOD;
				}
		}
		if(!ri) for(int i = 0;i < n;++ i) for(int j = 0;j < n;++ j) a[i][j] = tmp[i][j];
		return ret;
	}
	
	Matrix inv(bool ri = 1)
	{
		if(!ri) for(int i = 0;i < n;++ i) for(int j = 0;j < n;++ j) tmp[i][j] = a[i][j];
		Matrix ret; ret.n = n; for(int i = 0;i < n;++ i) ret.a[i][i] = 1;
		for(int i = 0;i < n;++ i)
		{
			if(!a[i][i]) for(int j = i;j < n;++ j) if(a[j][i]) {swap(a[i],a[j]);swap(ret.a[i],ret.a[j]);break;}
			if(!a[i][i]) break;//impossible
			for(int j = 0;j < n;++ j)
				if((i^j) && a[j][i])
				{
					int mul = 1ll * a[j][i] * qpow(a[i][i],MOD-2) % MOD;
					for(int k = i;k < n;++ k) a[j][k] = ((a[j][k] - 1ll * mul * a[i][k]) % MOD + MOD) % MOD;
					ret.Add(i,j,MOD-mul);
				}
		}
		for(int i = 0;i < n;++ i) ret.Mul(i,qpow(a[i][i],MOD-2));//a[i][i] = 1;
		if(!ri) for(int i = 0;i < n;++ i) for(int j = 0;j < n;++ j) a[i][j] = tmp[i][j];
		return ret;
	}
	
	Matrix Getq(bool ri = 1)//Aq = 0, to get q
	{
		if(!ri) for(int i = 0;i < n;++ i) for(int j = 0;j < n;++ j) tmp[i][j] = a[i][j];
		Matrix ret; ret.n = n;
		for(int i = 0;i < n;++ i)
		{
			if(!a[i][i]) for(int j = i+1;j < n;++ j) if(a[j][i]) {swap(a[i],a[j]);break;}
			if(!a[i][i]) 
			{
				ret.a[i][0] = 1;
				for(int j = i-1;j >= 0;-- j) ret.a[j][0] = (MOD-a[j][i])%MOD;
				for(int j = i-1;j >= 0;-- j)
				{
					ret.a[j][0] = 1ll * ret.a[j][0] * qpow(a[j][j],MOD-2) % MOD; //a[j][j] = 1;
					for(int k = j-1;k >= 0;-- k) ret.a[k][0] = ((ret.a[k][0] - 1ll * ret.a[j][0] * a[k][j]) % MOD + MOD) % MOD;
				}
				break;
			}
			for(int j = i+1;j < n;++ j)
				if(a[j][i])
				{
					int mul = 1ll * a[j][i] * qpow(a[i][i],MOD-2) % MOD;
					for(int k = i;k < n;++ k) a[j][k] = ((a[j][k] - 1ll * mul * a[i][k]) % MOD + MOD) % MOD;
				}
		}
		if(!ri) for(int i = 0;i < n;++ i) for(int j = 0;j < n;++ j) a[i][j] = tmp[i][j];
		return ret;
	}
	
	Matrix Del(int r,int c)//delete row r & column c
	{
		Matrix ret; ret.n = n-1;
		for(int i = 0;i < n;++ i)
			for(int j = 0;j < n && (i^r);++ j)
				if(j^c)
					ret.a[i-(i>r)][j-(j>c)] = a[i][j];
		return ret;
	}
}A,B,p,q;

int main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	for(int T = Read(),rk; T ;-- T)
	{
		A.Get(n = Read()); rk = A.Rank(0);
		if(rk == n)
		{
			B = A.inv(0);
			B.Mul(A.Det());
			B.Trans();
		}
		else if(rk < n-1)
		{
			for(int i = 0;i < n;++ i)
				for(int j = 0;j < n;++ j)
					putchar('0'),putchar(j == (n-1) ? '\n' : ' ');
			putchar('\n'); continue;
		}
		else
		{
			q = A.Getq(0);//Aq = 0
			p = ((A.TransNd()).Getq()).TransNd();//pA = 0
			int r = 0,c = 0;
			for(int i = 0;i < n;++ i) if(p.a[0][i]) {r = i;break;}
			for(int i = 0;i < n;++ i) if(q.a[i][0]) {c = i;break;}
			B.n = n;
			B.a[r][c] = ((r+c) & 1 ? MOD-1ll : 1) * A.Del(r,c).Det() % MOD;
			int iv = 1ll * qpow(p.a[0][r],MOD-2) * qpow(q.a[c][0],MOD-2) % MOD;
			for(int i = 0;i < n;++ i) 
				for(int j = 0;j < n;++ j)
					B.a[i][j] = 1ll * iv * p.a[0][i] % MOD * q.a[j][0] % MOD * B.a[r][c] % MOD;
		}
		for(int i = 0;i < n;++ i)
			for(int j = 0;j < n;++ j)
				Put((B.a[i][j] * ((i+j) & 1 ? -1 : 1) + MOD) % MOD,j == (n-1) ? '\n' : ' ');
		putchar('\n');
	}
	return (0-0);
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM