• Public model for matrix


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

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

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

    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;
    

      

  • 相关阅读:
    VirtualBox+Windbg 进行双机调试的方法
    (串口通信编程) 开源串口调试助手Common (Com Monitor)
    Win32SDK中(串行)通信资源概要(不断更新)
    对WDK中LIST_ENTRY的遍历
    用C语言写的一个控制台界面的通讯录管理系统
    我对Windows桌面任务栏自动隐藏功能的一点小小改进不再自动弹出(20130226更新)
    对WDK中对LIST_ENTRY的操作的相关函数的实现及简单运用
    我对CONTAINING_RECORD宏的详细解释
    基于51单片机实现模拟IIC总线时序
    uploadfy 常见问题收集
  • 原文地址:https://www.cnblogs.com/JYYHH/p/11858265.html
Copyright © 2020-2023  润新知