zoukankan      html  css  js  c++  java
  • 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;
    

      

  • 相关阅读:
    Java对象的生命周期与作用域的讨论(转)
    [置顶] Oracle学习路线与方法
    Java实现 蓝桥杯 算法训练 未名湖边的烦恼
    Java实现 蓝桥杯 算法训练 未名湖边的烦恼
    Java实现 蓝桥杯 算法训练 未名湖边的烦恼
    Java实现 蓝桥杯 算法训练 最大的算式
    Java实现 蓝桥杯 算法训练 最大的算式
    Java实现 蓝桥杯 算法训练 最大的算式
    Java实现 蓝桥杯 算法训练 最大的算式
    Java实现 蓝桥杯 算法训练 最大的算式
  • 原文地址:https://www.cnblogs.com/JYYHH/p/11858265.html
Copyright © 2011-2022 走看看