P4783 【模板】矩阵求逆

题目描述

求一个$N\times N$的矩阵的逆矩阵。答案对$10^9+7$取模。

输入输出格式

输入格式:

第一行有一个整数$N$,代表矩阵的大小;

从第$2$行到第$N+1$行,每行$N$个整数,其中第$i+1$行第$j$列的数代表矩阵中的元素$a_{ij}$。

输出格式:

若矩阵可逆,则输出$N$行,每行$N$个整数,其中第$i$行第$j$列的数代表逆矩阵中的元素 $b_{ij}$,答案对$10^9+7$取模;

否则只输出一行 No Solution

输入输出样例

输入样例#1:
复制

3
1 2 8
2 5 6
5 1 2
输出样例#1:
复制

718750005 718750005 968750007
171875001 671875005 296875002
117187501 867187506 429687503
输入样例#2:
复制

3
3 2 4
7 2 9
2 4 3
输出样例#2:
复制

No Solution

说明

对30%的数据有$N\le 100$;

对100%的数据有$N\le 400$,所有$a_{ij}<10^9+7$。

ps.TLE的同学可以试试大力卡常,标算不开O2勉强能卡过去的

bztMinamoto的题解

定义矩阵的三种初等行变换:

  1. 交换某两行。

  2. 将某一行的所有元素乘上\(k\)(\(k\neq 0\))。

  3. 将某一行的所有元素乘上\(k\)加到另一行去。

每一个初等变换都对应一个初等矩阵,即矩阵\(A\)做某一线性变换等价于用一个对应的初等矩阵左乘\(A\)。若有一堆初等变换\(1,2,...l\),对应的初等矩阵分别为\(P_1,P_2,...,P_l\),那么经过这些线性变换后的矩阵即为\(P_l....P_2P_1A=PA\)(\(P\)为之前那堆东西的乘积)。

对于一个矩阵\(A\),\(A\)可逆的充分必要条件是\(A\)经过若干次初等行变换可以变成\(E\)(\(E\)即单位矩阵),即存在一个矩阵\(P\)使得\(PA=E\),则\(P=A^{-1}\)。

通过初等行变换使得\(A\)变为\(E\)并不困难,可以用高斯消元解决,先消成上三角矩阵,然后再消成对角矩阵。

考虑怎么求出\(P\),因为有\(PA=E,PE=P\),如果我们同时维护两个矩阵\(A,B\),令\(B\)一开始时等于\(E\),在把\(A\)变为\(E\)的过程中对\(B\)也做相等的初等变换,那么当\(A\)变为\(E\)时,\(B\)也就变为了\(P\)(因为做初等行变换等价于被对应的初等矩阵左乘)。

如果在高斯消元的过程中发现无法将\(A\)变为\(E\),输出无解即可。\(O(n^3)\)。

注意为了卡常我们可以只对\(A\)的下三角消元,但是不能对\(B\)这样做,道理显然。

#include<bits/stdc++.h>
#define co const
#define il inline
using namespace std;
typedef long long LL; co int mod=1000000000+7;
il int add(int a,int b){
return (a+=b)>=mod?a-mod:a;
}
il int mul(int a,int b){
return (LL)a*b%mod;
}
int fpow(int a,int b){
int ans=1;
for(;b;b>>=1,a=mul(a,a))
if(b&1) ans=mul(ans,a);
return ans;
} co int N=401;
int n,a[N][N],b[N][N];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;b[i][i]=1,++i)
for(int j=1;j<=n;++j) scanf("%d",a[i]+j);
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]),swap(b[i],b[j]);break;}
}
if(!a[i][i]) return puts("No Solution"),0;
int inv=fpow(a[i][i],mod-2);
for(int k=1;k<=n;++k) a[i][k]=mul(a[i][k],inv),b[i][k]=mul(b[i][k],inv); // edit !:do all
for(int j=1;j<=n;++j)if(j!=i){
int coef=a[j][i];
for(int k=1;k<=n;++k) a[j][k]=add(a[j][k],mod-mul(coef,a[i][k])),b[j][k]=add(b[j][k],mod-mul(coef,b[i][k]));
}
}
for(int i=1;i<=n;puts(""),++i)
for(int j=1;j<=n;++j) printf("%d ",b[i][j]);
return 0;
}

LG4783 【模板】矩阵求逆的更多相关文章

  1. luoguP4783 [模板]矩阵求逆 线性代数

    求\(n^2\)的矩阵的逆 翻了翻题解,看到了初等矩阵这个东西,突然想起来在看线代的时候看到过.... 然后又温习了一遍线性代数的知识 不妨设\(PA = E\),其中\(P\)是一堆初等矩阵的积(必 ...

  2. matrix矩阵求逆 与解方程模板 留做备用 (有bug,待补充)

    // // main.cpp // 矩阵求逆 // // Created by 唐 锐 on 13-6-20. // Copyright (c) 2013年 唐 锐. All rights reser ...

  3. P4783 【模板】矩阵求逆

    原题链接 https://www.luogu.org/problemnew/show/P4783 一道模板题,更重要的省选难度..... 题目要求的是一个n*n的逆矩阵,还要对大数取膜. 普通高中生: ...

  4. 洛谷 P4783 【模板】矩阵求逆

    题目分析 模板题. #include <bits/stdc++.h> using namespace std; typedef long long ll; const int mod=1e ...

  5. LUOGU P4783 【模板】矩阵求逆(高斯消元)

    传送门 解题思路 用高斯消元对矩阵求逆,设\(A*B=C\),\(C\)为单位矩阵,则\(B\)为\(A\)的逆矩阵.做法是把\(B\)先设成单位矩阵,然后对\(A\)做高斯消元的过程,对\(B\)进 ...

  6. 题解 P4783 【【模板】矩阵求逆】

    题目大意 求一个N×N的矩阵的逆矩阵.答案对10^9+7取模.N<=400 前置知识 矩阵的初等变换 矩阵的逆定义为 A*B=E(E为单位矩阵)此时B为A的逆 思路 如果矩阵有逆 那么这个矩阵经 ...

  7. Luogu4783 【模板】矩阵求逆(高斯消元)

    对矩阵进行高斯消元直至消为单位矩阵,并在另一个单位矩阵上对其做同样的操作即可. 模意义下的高斯消元可以直接计算系数来避免整行的辗转相除. 还不知道有什么用. #include<iostream& ...

  8. 洛谷P4783 【模板】矩阵求逆(高斯消元)

    题意 题目链接 Sol 首先在原矩阵的右侧放一个单位矩阵 对左侧的矩阵高斯消元 右侧的矩阵即为逆矩阵 // luogu-judger-enable-o2 #include<bits/stdc++ ...

  9. OpenCV2邻域和模板操作

    在图像处理中,通过当前位置的邻域像素计算新的像素值是很常见的操作.当邻域包含图像的上几行和下几行时,就需要同时扫描图像的若干行,这就是图像的邻域操作了.至于模板操作是实现空间滤波的基础,通常是使用一个 ...

随机推荐

  1. (CSDN迁移) 输入一个链表,从尾到头打印链表每个节点的值

    题目描述 输入一个链表,从尾到头打印链表每个节点的值. 思路1. 翻转链表,使用java自带的翻转函数或者从头到尾依次改变链表的节点指针 /** * public class ListNode { * ...

  2. Python Tkinter 窗口创建与布局

    做界面,首先需要创建一个窗口,Python Tkinter创建窗口很简单:(注意,Tkinter的包名因Python的版本不同存在差异,有两种:Tkinter和tkinter,读者若发现程序不能运行, ...

  3. pipeline的添加顺序和执行顺序

    原文链接:https://www.cnblogs.com/ruber/p/10186571.html 本文只想讨论一下pipeline的执行顺序问题,因为这个搞不明白就不知道先添加编码还是解码,是不是 ...

  4. spring项目配置双数据源读写分离

    我们最早做新项目的时候一直想做数据库的读写分离与主从同步,由于一些原因一直没有去做这个事情,这次我们需要配置双数据源的起因是因为我们做了一个新项目用了另一个数据库,需要把这个数据库的数据显示到原来的后 ...

  5. 12 IO流(九)——装饰流 BufferedInputStream/OutputStream

    我们按功能可以将IO流分为节点流与处理流 节点流:可以直接从数据源或目的地读写数据 处理流(装饰流):不直接连接到数据源或目的地,是其他流(必须包含节点流)进行封装.目的主要是简化操作和提高性能. B ...

  6. 基于全志a33-vstar开发板的ap6210WiFi模块移植

    可以去链接看更详细的,第一次用博客,这个编辑方式太不友好了. 文档:全志a33--系统移植--ap6210WiFi模块移?..链接:http://note.youdao.com/noteshare?i ...

  7. hdu1016 Prime Ring Problem【素数环问题(经典dfs)】

    Prime Ring Problem Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

  8. springboot笔记09——使用aop

    什么是AOP? aop(Aspect Oriented Programming)面向切面编程,是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP引入封装 ...

  9. 每周分享五个 PyCharm 使用技巧(四)

    文章首发于 微信公众号:Python编程时光 PyCharm 是大多数 Python 开发者的首选 IDE,每天我们都在上面敲着熟悉的代码,写出一个又一个奇妙的功能. 一个每天都在使用的工具,如果能掌 ...

  10. java容易混淆的概念

    容易混淆的内容 1.JVM内存模型 2.Java内存模型 3.Java对象模型 JVM内存模型 1.堆 2.虚拟机栈 3.本地方法栈 4.程序计数器 5.方法区 Java内存模型 Java堆和方法区的 ...