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

这是一道线性代数的好题

调死我这个大菜鸡了

如果您还不太清楚线性代数的话,那么我可以跟您讲一个笑话:

有人在盘点世界上吊死人最多的树
据说是美国还是法国的哪片森林里的
其实这完全是瞎扯
他们怕是不知道,有一种叫做“线性代数”的树
上面吊死的人远比那些树多得多

嗯嗯,笑话讲完了,我们来做题吧qwq

在看这篇题解之前,需要了解的芝士:

1.高斯-约旦消元法

2.矩阵的基本知识(矩阵的初等变换,单位矩阵等等)

应该都好理解的吧(至于我为什么不用高斯消元,是因为我个人认为,高斯消元的精度不是很高,代码有些长 所以不好背


首先来讲一讲什么是矩阵求逆

题目告诉我们一个矩阵(A),让我们求得一个矩阵(B),使得(AB=BA=I)

那么问题来了,这个矩阵(I)是个smg?

矩阵(I)就是传说中的单位矩阵

这是一个(4 imes4)的单位矩阵

[I=egin{bmatrix}1&0&0&0\0&1&0&0\0&0&1&0\0&0&0&1end{bmatrix} ]

看到了嘛,单位矩阵就是一条对角线上都是1,余都为0的矩阵。

说白了,就是求(B=I/A)这个东西

可惜好像矩阵运算里没有除法

我上面那个表达式也是不合法的

然后我们就会用BFS(Baidu First Search)去找思路

求逆思路:

1.把(A)和它等大的单位矩阵(I)放在一个矩阵里

2.对(A)进行高斯消元使(A)化成单位矩阵

3.此时原来单位矩阵转化成逆矩阵

意不意外?惊不惊喜?

知道了具体的过程,我们就可以来搞事情了,把P3389的程序复制粘贴过来……

然后修改一下,加上右边的矩阵(I),修改一下输出,然后……

({color{Red}WA})

是我沙雕了……两个题目的数据类型都不一样啊啊啊啊啊啊啊

高斯消元是(Double)的,但是这道题……(long;long)……

还带着除法……

所以话说乘法逆元是个好东西

然后把数据类型改一下,写个龟速幂套乘法逆元,然后……

({color{Red}WA})

嘤嘤嘤嘤嘤嘤嘤嘤嘤嘤嘤嘤嘤嘤嘤嘤嘤嘤……

然后我借鉴了一下题解,发现是%运算的锅,因为这个很可能出现负数,然后就会({color{Red}WA})掉。

比如我的({color{green}AC})程序里有这个:

a[j][k]=(a[j][k]%mod+mod)%mod;

和之前({color{red}WA})这个:

a[j][k]%=mod;

是不一样的。

上面的那个确保了没有负数(Maybe

所以说,%这个运算最好用在膜拜管理员/神仙/巨佬中,如果题目里有模数,那么……我多半会挂掉……

({color{green}AC})程序:

#include <bits/stdc++.h>
using namespace std;
const long long mod=1e9+7;
long long a[500][1000];
long long IE(long long m,long long n)
{
  long long p=1;
  while(n)
  {
    if(n%2==1) p=(p*m)%mod;
    m=m*m%mod;
    n/=2;
  }
  return p%mod;
}
int main()
{
  long long n;
  cin>>n;
  for(int i=1; i<=n; i++)
    for(int j=1; j<=n; j++)
      cin>>a[i][j];
  for(int i=1; i<=n; i++) a[i][i+n]=1;
  for(int i=1; i<=n; i++)
  {
    int tx=i;
    for(int j=i+1; j<=n; j++)
      if(abs(a[j][i])>abs(a[tx][i])) tx=j;
    if(i!=tx)
    {
      for(int j=1; j<=n*2; j++)
        swap(a[i][j],a[tx][j]);
    }
    if(!a[i][i])
    {
      cout<<"No Solution";
      return 0;
    }
    int I=IE(a[i][i],mod-2);
    for (int j=1; j<=n; j++)
      if(j!=i)
      {
        long long t=a[j][i]*I%mod;
        for (int k=i; k<=n*2; k++)
        {
          a[j][k]-=a[i][k]*t;
          a[j][k]=(a[j][k]%mod+mod)%mod;
        }
      }
    for(int j=1; j<=2*n; j++)
      a[i][j]=a[i][j]*I%mod;
  }
  for(int i=1; i<=n; i++)
  {
    for(int j=n+1; j<=n*2; j++)
      cout<<a[i][j]<<" ";
    cout<<endl;
  }
}

就是这样子吧……线性代数真的是毒瘤……喵喵喵~~~

原文地址:https://www.cnblogs.com/oierscw/p/12722169.html