高斯约旦消元法求逆矩阵的思想(分块矩阵的逆矩阵)

P4783【模板】矩阵求逆题目描述求一个N×NN×NN×N的矩阵的逆矩阵。答案对109+710^9+7109+7取模。1.逆矩阵的定义假设AAA是一个方阵,如果存在一个矩阵A−1A^{-1}A−1,使得A−1A=IA^{-1}A=IA−1A=I并且AA−1=IAA^{-1}=IAA−1=I那么,矩阵A就是可逆的,A−1A^{-1}A−1称为A的逆矩阵2.逆矩阵求…

大家好,又见面了,我是你们的朋友全栈君。

luogu P4783 【模板】矩阵求逆

题目描述

求一个 N × N N×N N×N的矩阵的逆矩阵。答案对 1 0 9 + 7 10^9+7 109+7取模。

1.逆矩阵的定义

假设 A A A 是一个方阵,如果存在一个矩阵 A − 1 A^{-1} A1,使得
A − 1 A = I A^{-1}A=I A1A=I
并且
A A − 1 = I AA^{-1}=I AA1=I

那么,矩阵 A 就是可逆的, A − 1 A^{-1} A1 称为 A 的逆矩阵

2.逆矩阵求法 —— 初等变换法(高斯-约旦消元)

0.高斯-约旦消元

详见P3389 【模板】高斯消元法题解部分

高斯约旦消元与高斯消元区别:

高斯消元 -> 消成上三角矩阵 

高斯-约旦消元 -> 消成对角矩阵 

约旦消元法的精度更好,代码更简单,没有回带的过程

void Gauss_jordan(){ 
   
	/***** 行的交换&加减消元 *****/ 
	for(re int i=1,r;i<=n;++i){ 
   	//正在处理第i行 
		r=i;
		for(re int j=i+1;j<=n;++j) 
			if(fabs(a[j][i])>fabs(a[r][i])) r=j;
		if(fabs(a[r][i])<eps){ 
   
			puts("No Solution");return;
		}
		if(i!=r) swap(a[i],a[r]);
		
		for(re int k=1;k<=n;++k){ 
   
		//每一行都处理 
			if(k==i) continue;
			double p=a[k][i]/a[i][i];
			for(re int j=i;j<=n+1;++j) a[k][j]-=p*a[i][j];
		} 
	}	
	
	//上述操作后会剩下对角矩阵,答案要除以系数 
	for(re int i=1;i<=n;++i) printf("%.2lf\n",a[i][n+1]/a[i][i]);
}

1.矩阵求逆

思路

  • A A A的逆矩阵,把 A A A和单位矩阵 I I I放在一个矩阵里
  • A A A进行加减消元使 A A A化成单位矩阵
  • 此时原来单位矩阵转化成逆矩阵

原理
A − 1 ∗ [ A I ] = [ I A − 1 ] A^{-1} * [AI] = [I A^{-1}] A1[AI]=[IA1]

举个栗子

[ 2 − 1 0 − 1 2 − 1 0 − 1 2 ] \left[ \begin{matrix} 2 &amp; -1 &amp; 0 \\ -1 &amp; 2 &amp; -1 \\ 0 &amp; -1 &amp; 2 \end{matrix} \right] 210121012

首先
[ 2 − 1 0 1 0 0 − 1 2 − 1 0 1 0 0 − 1 2 0 0 1 ] \begin{bmatrix} 2 &amp; -1 &amp; 0 &amp; 1 &amp; 0 &amp; 0 \\ -1 &amp; 2 &amp; -1 &amp; 0 &amp; 1 &amp; 0 \\ 0 &amp; -1 &amp; 2 &amp; 0 &amp; 0 &amp; 1 \end{bmatrix} 210121012100010001
对左边进行消元可得
[ 2 − 1 0 1 0 0 0 3 2 − 1 1 2 1 0 0 0 4 3 1 3 2 3 1 ] \left[ \begin{matrix} 2 &amp; -1 &amp; 0 &amp; 1 &amp; 0 &amp; 0 \\ 0 &amp; \frac{3}{2} &amp; -1 &amp; \frac{1}{2} &amp; 1 &amp; 0 \\ 0 &amp; 0 &amp; \frac{4}{3} &amp; \frac{1}{3} &amp; \frac{2}{3} &amp; 1 \end{matrix} \right] 20012300134121310132001
此时已消成上三角矩阵,高斯消元开始回代,但约旦会消成对角矩阵
[ 2 0 0 3 2 1 1 2 0 3 2 0 3 4 3 2 3 4 0 0 4 3 1 3 2 3 1 ] \left[ \begin{matrix} 2 &amp; 0 &amp; 0 &amp; \frac{3}{2} &amp; 1 &amp; \frac{1}{2} \\ 0 &amp; \frac{3}{2} &amp; 0 &amp; \frac{3}{4} &amp; \frac{3}{2} &amp; \frac{3}{4} \\ 0 &amp; 0 &amp; \frac{4}{3} &amp; \frac{1}{3} &amp; \frac{2}{3} &amp; 1 \end{matrix} \right] 200023000342343311233221431
最后每行除以系数
[ 1 0 0 3 4 1 2 1 4 0 1 0 1 2 1 1 2 0 0 1 1 4 1 2 3 4 ] \left[ \begin{matrix} 1 &amp; 0 &amp; 0 &amp; \frac{3}{4} &amp; \frac{1}{2} &amp; \frac{1}{4} \\ 0 &amp; 1 &amp; 0 &amp; \frac{1}{2} &amp; 1 &amp; \frac{1}{2} \\ 0 &amp; 0 &amp; 1 &amp; \frac{1}{4} &amp; \frac{1}{2} &amp; \frac{3}{4} \end{matrix} \right] 10001000143214121121412143
此时右半边即为所求

2.细节

  1. 开long long(不要冒风险,乘法很容易溢出)
  2. 模意义下除以一个数等于乘上逆元,可用快速幂求逆元(费马小定理)

C o d e Code Code

#include<iostream>
#include<cstdio>
#include<cmath>
#define re register
#define il inline
#define ll long long
using namespace std;

il ll read(){ 
   
    ll s=0,f=0;char c=getchar();
    while(c<'0'||c>'9') f=(c=='-'),c=getchar();
    while(c>='0'&&c<='9') s=(s<<3)+(s<<1)+(c^'0'),c=getchar();
    return f?-s:s;
}

const int N=405,mod=1e9+7;
int n;
ll a[N][N<<1];
il ll qpow(ll x,ll k){ 
   
	ll ans=1;
	while(k){ 
   
		if(k&1) ans=ans*x%mod;
		x=x*x%mod;
		k>>=1;
	}
	return ans%mod;
}

il void Gauss_j(){ 
   	
	for(re int i=1,r;i<=n;++i){ 
   
		r=i;
		for(re int j=i+1;j<=n;++j)
			if(a[j][i]>a[r][i]) r=j;
		if(r!=i) swap(a[i],a[r]);
		if(!a[i][i]){ 
   puts("No Solution");return;}
		
		int kk=qpow(a[i][i],mod-2);	//求逆元 
		for(re int k=1;k<=n;++k){ 
   
			if(k==i) continue;
			int p=a[k][i]*kk%mod;
			for(re int j=i;j<=(n<<1);++j) 
				a[k][j]=((a[k][j]-p*a[i][j])%mod+mod)%mod;
		} 
		
		for(re int j=1;j<=(n<<1);++j) a[i][j]=(a[i][j]*kk%mod);
		//更新当前行 如果放在最后要再求一次逆元,不如直接放在这里 
	}	
	
	for(re int i=1;i<=n;++i){ 
   
		for(re int j=n+1;j<(n<<1);++j) printf("%lld ",a[i][j]);
		printf("%lld\n",a[i][n<<1]);
	}
}
int main(){ 
   
	n=read();
	for(re int i=1;i<=n;++i)
		for(re int j=1;j<=n;++j)
			a[i][j]=read(),a[i][i+n]=1;
	
	Gauss_j();
    return 0;
}

网上浏览一圈头都要炸掉,线性代数太可怕了,定义好多
最后只看懂了这种方法

有什么问题欢迎评论区指出 :)

参考文章

线性代数之——矩阵乘法和逆矩阵

逆矩阵的几种求法与解析(很全很经典)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/129183.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • HTTP和HTTPS 之间的区别

    HTTP和HTTPS 之间的区别

  • PyCharm创建一个新的项目

    PyCharm创建一个新的项目欢迎使用PyCharm这是第一次使用PyCharm,如果你想学习如何使用PyCharm创建一个新的项目,可以仔细阅读这篇文章,了解一下。打开PyCharm点击创建一个新项目选择保存的目录(建议D盘),刚刚安装的默认选择新建环境,点击创建下载配置解释器Python3.8进行中开始创建以“.py”为后缀写个简单的helloworld!运行一下结果如下可以用一个子目录打包需要写的东西同样的操作这次写个learnPython,看看效果,前后对比还有文件存储

  • 十种常用代码编辑器

    十种常用代码编辑器1.vscode微软推出的轻量级代码编译器,是本人使用最多的编译器(主要是好玩的插件多),支持几乎所有主流的开发语言的语法高亮、智能代码补全、自定义热键、括号匹配、代码片段、代码对比Diff、GIT等特性,支持插件扩展,并针对网页开发和云端应用开发做了优化。分享下本人的死宅背景~2.NETBEANSNetBeans是Sun公司(2009年被甲骨文收购)在2000年创立的开放源代码供开发人员和客户社区的家园,旨在构建世界级的JavaIDE。NetBeans当前可以在Solaris、Win

  • Mac中vim永久显示行号「建议收藏」

    步骤1:cp/usr/share/vim/vimrc~/.vimrc 先复制一份vim配置模板到个人目录下步骤2:  vim ~/.vimrc 再进入insert模式,在最后加二行 syntaxon setnu!最后wq保存再次进入到vim就会永久显示行号,不用每次都setnu!…

  • Android Material design

    Android Material design

  • 3D游戏模型是怎么制作出来的?[通俗易懂]

    现在游戏建模这个行业非常热门,因此有很多小伙伴梦想成为一名游戏模型师,但是很多都对这个工作需要做什么了解不深,这里我简单介绍一下我从事的3D游戏模型制作。1.我们都知道游戏模型制作肯定是需要建模的,建模是游戏设计中最重要的环节,占整个模型制作的70%,建模的方法很多,游戏模型常用的软件有3DMAX(游戏制作中使用的软件很多都是英文版,建议学习从英文软件开始)建模的难度在所有职业中是最高最全面的,从桌椅到星舰,巨型BOSS等等复杂的模型,模型这方面没有什么多说的,练习是最重要的。具体的方法技巧可.

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号