• 题解 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;
      }
    }
    

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

  • 相关阅读:
    瑞游天翼客户端win7,win8,win10
    js循环POST提交添加辅助单位
    服务器状态检测(1)
    快速切换天财商龙门店后台.VB6.0
    大批量删除农行点菜宝菜品品相和房间
    社会工程学
    你还会记得吗
    优酷爆个人数据漏洞
    win8删除无线网络其中的一项配置
    穿越火线修改成宽屏模式
  • 原文地址:https://www.cnblogs.com/oierscw/p/12722169.html
Copyright © 2020-2023  润新知