[总结] 行列式

[总结] 行列式

概念类

数学家想找到一个由矩阵到数字的映射 f:M(R)>R,于是有了行列式。

f 满足以下条件:

  • 行线性
  • 行交错性
  • 规范性

称这个函数值为行列式函数。

行线性

  1. 对矩阵一行乘上一个数 k,函数值也乘上一个数 k
  2. 把矩阵第 i 行加到第 j(ij) 上,函数值不变。

f(a1a2×kan)=f(a1a2an)×k

f(a1aiajan)=f(a1ai+ajajan)

行交错性

如果一个矩阵有两行相等,那么行列式函数值为 0

f(a1aiaian)=0

规范性

f(In)=1

其中 In 表示 n单位方阵

性质

  • 矩阵转置,行列式值不变。
  • 矩阵行(列)交换,行列式值取反。
  • 矩阵行(列)相加或相减,行列式值不变。
  • 矩阵行(列)所有元素同时乘以数 k,矩阵等比例变大。

考虑利用行线性的性质来证明第二条。

f(a1aiajan)=f(a1ai+ajajan),f(a1ajajan)=0

可以得到:

f(a1aiajan)+f(a1ajajan)=f(a1ai+ajajan)

也就是说:在这种情况下,两个矩阵“相加”的行列式值可以拆分成两个“子矩阵”行列式值的和

所以:

f(a1aiajan)+f(a1ajaian)=f(a1ai+ajai+ajan)=0

从而得到:

f(a1aiajan)=f(a1ajaian)

行列式函数的性质

行列式函数的构造及其唯一性的证明

|det(A)|=np(1)τ(p)i=1nAi,pi

证明的大体思路是把每一个向量 ai 拆成线性组合的形式,把系数提出来,最后发现有贡献的一定是排列,因为有重复行的矩阵函数值为 0

这是行列式函数的核心所在,基本上所有的题都是根据这个公式表现出来的。

关键词:逆序对,奇数比偶数多多少

行列式的求解

利用通项公式来理解计算过程

核心是消成上三角矩阵,对角线乘积就是函数值。

这是因为削成上三角矩阵后行列式函数值不变,而且排列 p 的选取在有值的情况下唯一。

  1. 高斯消元法(非约旦)。

适用于整数有逆元或者小数的情况。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 600 + 10;
int n,P;
#define LL long long
#define read() read<int>()
LL a[maxn][maxn];
int main(){
	n=read();P=read();
	for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)G[i][j]=read<LL>();
	LL ans=1;
	for(int i=1;i<=n;i++){
		if(!a[i][i]){
			for(int j=i+1;j<=n;j++)if(a[j][i]){
				swap(a[i],a[j]);ans=(P-ans);
				break;
			}
		}
		if(!a[i][i]){
			ans=0;break;
		}
		ans=1LL*ans*a[i][i];
		LL inv=power(a[i][i],P-2);
		for(int j=i+1;j<=n;j++){
			LL t=a[j][i]*inv%P;
			for(int k=i;k<=n;k++)a[j][k]=(a[j][k]-t*a[i][k]%P+P)%P;
		}
	}
	printf("%lld\n",ans);
	return 0;
}
  1. 辗转相除法。

注意,复杂度是 O(n2(n+logn)) 的。

适用于 P 非质数的情况。

行列式非零当且仅当矩阵的秩是 n ,也就是满秩。

每次选取尽量小的数字作为辗转相除时的 b,常数小。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 600 + 10;
int n,P;
#define LL long long
#define read() read<int>()
LL G[maxn][maxn];
int main(){
	n=read();P=read();
	for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)G[i][j]=read<LL>();
	LL ans=1;
	for(int i=1;i<n;i++){
		for(int j=i+1;j<=n;j++){
			while(G[j][i]){
				LL t=G[i][i]/G[j][i];
				for(int k=i;k<=n;k++)G[i][k]=(G[i][k]-t*G[j][k]%P+P)%P;
				swap(G[i],G[j]);ans=(P-ans);
			}
		}
	}
	for(int i=1;i<=n;i++)ans=1LL*ans*G[i][i]%P;
	printf("%lld\n",ans);
	return 0;
}
posted @   ¶凉笙  阅读(708)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示