Public model for matrix

   以下是可以加减乘除(就是乘逆矩阵啦)以及求若干次幂、行列式和逆的矩阵模板。

欢迎大家指正其中可能存在的错误(只验证了求逆的正确性)。

   顺便提一下这种复杂度低于定义式求逆的方法,来自于我的高等代数书,思想就是对分块矩阵(A E)进行行变换从而得到(E A^-1),复杂度与消元一样,都是 O(N^3)的。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
const int N=405,ha=1e9+7;
 
inline int add(int x,int y){ x+=y; return x>=ha?x-ha:x;}
inline void ADD(int &x,int y){ x+=y; if(x>=ha) x-=ha;}
 
inline int ksm(int x,int y){
    int an=1;
    for(;y;y>>=1,x=x*(ll)x%ha) if(y&1) an=an*(ll)x%ha;
    return an;
}
inline int Get_inv(int x){ return ksm(x,ha-2);}
 
struct matrix{
    int a[N][N],n;
     
    inline void clear(){ memset(a,0,sizeof(a));}
    inline void Base(){ clear(); for(int i=1;i<=n;i++) a[i][i]=1;}
     
    inline void input(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++) scanf("%d",a[i]+j);
    }
    inline void output(){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++) printf("%d ",a[i][j]);
            puts("");
        }
    }
     
    inline void swap(int x,int y){
        for(int i=1;i<=n;i++) swap(a[x][i],a[y][i]);
    }
    inline void add(int from,int tmp,int to){
        for(int i=1;i<=n;i++) ADD(a[to][i],a[from][i]*(ll)tmp%ha);
    }
    inline void mul(int x,int ml){
        for(int i=1;i<=n;i++) a[x][i]=a[x][i]*(ll)ml%ha;
    }
     
    inline int Determinant(){
        int an=1;
        matrix b=*this;
         
        for(int i=1,o,inv;i<=n;i++){
            for(o=i;o<=n;o++) if(b.a[o][i]) break;
            if(o>n) return 0;
            if(o>i){ an=ha-an; b.swap(o,i);}
             
            inv=Get_inv(b.a[i][i]);
            for(int j=i+1,tmp;j<=n;j++) if(b.a[j][i])
                tmp=ha-inv*(ll)b.a[j][i]%ha,b.add(i,tmp,j);
             
            an=an*(ll)b.a[i][i]%ha;
        }
         
        return an;
    }
     
    inline matrix ni(){
        matrix b; b.n=n,b.Base();
         
        if(!Determinant()) b.clear();
        else{
             
            //先化成对角线元素都是1的上三角矩阵
             
            for(int i=1,o,inv;i<=n;i++){
                for(o=i;o<=n;o++) if(a[o][i]) break;
                if(o>i) swap(o,i),b.swap(o,i);
                 
                inv=Get_inv(a[i][i]),mul(i,inv),b.mul(i,inv);
                 
                for(int j=i+1,tmp;j<=n;j++) if(a[j][i])
                    tmp=ha-a[j][i],add(i,tmp,j),b.add(i,tmp,j);
            }
             
            //然后再把A消成单位矩阵
             
            for(int i=n-1;i;i--)
                for(int j=i+1;j<=n;j++) if(a[i][j]) b.add(j,ha-a[i][j],i),add(j,ha-a[i][j],i);
        }
         
        return b;
    }
     
    matrix operator +(const matrix &u){
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++) ADD(a[i][j],u.a[i][j]);
        return *this;
    }
     
    matrix operator -(const matrix &u){
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++) ADD(a[i][j],ha-u.a[i][j]);
        return *this;
    }
     
    matrix operator *(const matrix &u)const{
        matrix r; r.clear(),r.n=n;
        for(int k=1;k<=n;k++)
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++) ADD(r.a[i][j],a[i][k]*(ll)u.a[k][j]%ha);
        return r;
    }
     
    matrix operator /(matrix &u)const{
        return *this*u.ni();
    }
     
    matrix operator ^(int &u){
        matrix b,c=*this; b.n=n,b.Base();
        for(;u;u>>=1,c=c*c) if(u&1) b=b*c;
        return b;
    }
}JHY;

  

posted @   蒟蒻JHY  阅读(189)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· C++代码改造为UTF-8编码问题的总结
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
阅读排行:
· Deepseek官网太卡,教你白嫖阿里云的Deepseek-R1满血版
· 2分钟学会 DeepSeek API,竟然比官方更好用!
· .NET 使用 DeepSeek R1 开发智能 AI 客户端
· DeepSeek本地性能调优
· 一文掌握DeepSeek本地部署+Page Assist浏览器插件+C#接口调用+局域网访问!全攻略
点击右上角即可分享
微信分享提示