首页 > 其他分享 >「矩阵求逆」P4783 【模板】矩阵求逆

「矩阵求逆」P4783 【模板】矩阵求逆

时间:2023-02-12 11:35:40浏览次数:64  
标签:求逆 le int 矩阵 pos P4783 times

知识点:线性代数

Link:Luogu

大家好啊,我不会线代,下学期才开,所以这题抄的,只是简单记录做法,等到学了线代再回来更深一步理解。

但是这做法又易懂又好记又牛逼。

主要抄袭对象:https://www.luogu.com.cn/blog/_post/162629

不过在此之前需要担心一下开学的微积分考试妈的

简述

给定一 \(n\times n\) 的矩阵 \(A\),判断该矩阵是否可逆,如果可逆则求该矩阵的逆矩阵,答案对 \(10^9+7\) 取模。
\(1\le n\le 400\),\(0\le a_{i,j}< 10^9+7\)。
1S,128MB。

分析

这里仅给出一种使用高斯-约旦消元的做法。

记 \([AB]\) 表示将一个 \(n\times m_b\) 的矩阵 \(B\) 拼接一个 \(n\times m_a\) 的矩阵 \(A\) 之后形成的矩阵,即有:

\[[AB]_{i, j} = \begin{cases} A_{i, j} &(j\le m_a)\\ B_{i, j - m_a} &(m_a <j \le m_a+m_b) \end{cases}\]

记 \(I\) 为 \(n\times n\) 的单位矩阵,则有:

\[A^{-1}\times [AI] = [IA^{-1}] \]

则若我们可以通过对矩阵 \([AI]\) 进行若干操作使得矩阵的左半部分(即拼接后左半边的 \(A\))转化为单位矩阵 \(I\),则我们进行的操作等价于令 \(A^{-1}\) 乘上了矩阵 \([AI]\),则得到的矩阵的右半部分即为所求的逆矩阵 \(A^{-1}\)。

使用高斯-约旦法将 \([AI]\) 的左半边消成对角矩阵,再令每行除以系数即可。

由于是在模意义下,消元时的除法需要用逆元代替。

总复杂度 \(O(n^3)\) 级别。

代码

//By:Luckyblock
/*
*/
#include <cstdio>
#include <cctype>
#include <algorithm>
#define LL long long
const int kN = 410;
const LL p = 1e9 + 7;
//=============================================================
int n;
LL a[kN][kN << 1];
//=============================================================
inline int read() {
  int f = 1, w = 0; char ch = getchar();
  for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = - 1;
  for (; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + ch - '0';
  return f * w;
}
LL qpow(LL x_, LL y_) {
  LL ret = 1;
  while (y_) {
    if (y_ & 1) ret = ret * x_ % p;
    x_ = x_ * x_ % p, y_ >>= 1ll;
  }
  return ret;
}
bool Gauss_jordan() {
  for (int i = 1; i <= n; ++ i) {
    int pos = i;
    for (int j = i + 1; j <= n; ++ j) {
      if (a[j][i] > a[pos][i]) pos = j;
    }
    if (pos != i) std::swap(a[i], a[pos]);
    if (!a[i][i]) return false;

    LL inv = qpow(a[i][i], p - 2);
    for (int j = 1; j <= n; ++ j) {
      if (j == i) continue;
      LL delta = a[j][i] * inv % p;
      for (int k = 1; k <= 2 * n; ++ k) {
        a[j][k] = ((a[j][k] - delta * a[i][k]) % p + p) % p;
      }
    }
    for (int j = 1; j <= 2 * n; ++ j) a[i][j] = a[i][j] * inv % p;
  }
  return true;
}
//=============================================================
int main() {
  // freopen("1.txt", "r", stdin);
  n = read();
  for (int i = 1; i <= n; ++ i) {
    for (int j = 1; j <= n; ++ j) {
      a[i][j] = read(), a[i][i + n] = 1;
    }
  }
  if (!Gauss_jordan()) {
    printf("No Solution\n");
    return 0;
  }
  for (int i = 1; i <= n; ++ i) {
    for (int j = n + 1; j <= 2 * n; ++ j) {
      printf("%lld ", a[i][j]);
    }
    printf("\n");
  }
  return 0;
}

标签:求逆,le,int,矩阵,pos,P4783,times
From: https://www.cnblogs.com/luckyblock/p/17113494.html

相关文章

  • 矩阵树定理、BEST 定理
    说句闲话。今天翻到一篇博客上来给放了个公式:\[\sum_{i=0}^n\binom{2i}i\binom{2n-2i}{2i}=4^i\]看起来就很不对劲。然后爆算了一波确实是错的。敬请注意。然后不知道为......
  • 「解题报告」[省选联考 2021 A 卷] 矩阵游戏
    啥都不会了!啥都不会了!啥都不会了!啥都不会了!啥都不会了!啥都不会了!啥都不会了!啥都不会了!啥都不会了!啥都不会了!啥都不会了!啥都不会了!啥都不会了!啥都不会了!啥都不会了!啥都不会......
  • 重塑矩阵(力扣简单题)
    题目:在MATLAB中,有一个非常有用的函数reshape,它可以将一个mxn矩阵重塑为另一个大小不同(rxc)的新矩阵,但保留其原始数据。给你一个由二维数组mat表示的mxn矩......
  • 多项式求逆
    对于多项式\(f(x)\),求满足\(f(x)g(x)=1\pmod{x^n}\)的\(g(x)\)。其中取模的意义在于丢掉第\(n\)项后面的系数不管。一些dp题可能有形如\(f_i=\sum_jg_jf_......
  • 【数组】——螺旋矩阵
    【数组】——螺旋矩阵模拟顺时针画矩阵的过程:1.填充上行从左到右2.填充右列从上到下3.填充下行从右到左4.填充左列从下到上由外向内一圈一圈这么画下去。每一条边都......
  • 用行列式求4阶逆矩阵
    矩阵M的逆矩阵等于MT的C*1/detMC=Cofactory第一步转置 第二步就是求每个位置的代数余子式的值(举个例子M的a11就变为C11的值 ) 当前位置i+j奇偶决定正负4阶的Cij......
  • 在VSCode中的markdown里插入混淆矩阵HTML源码
    最近在看论文的时候习惯用markdown记录笔记,就有了如题的需求。由于原生的markdown不能合并表格的单元格(或者我不知道,OS:真菜),但是markdown支持HTML,直接写一段代码扔进去就......
  • Numpy中数组和矩阵操作的数学函数
    Numpy是一个强大的Python计算库。它提供了广泛的数学函数,可以对数组和矩阵执行各种操作。本文中将整理一些基本和常用的数学操作。基本数学运算:Numpy提供了许多基本......
  • 三种方法用Fortran求逆矩阵
    三种方法用Fortran求四阶矩阵的逆矩阵数值计算Crefertohttps://fortranwiki.org/fortran/show/Matrix+inversionSUBROUTINEMATINV(A,B)DIMENSION......
  • C语言填空:矩阵主次对角线置1和-1,其他元素为0
    #include<stdio.h>//程序功能:输入一个6*6矩阵,将其主对角线上的元素置1,次对角线置-1,其余元素为0main(){int【1】;inti,j;for(i=0;【2】;i++){......