高斯消元法

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高斯消元法相关的知识,希望对你有一定的参考价值。

高斯消元法

法1:高斯-约旦消元

思路

A X = B AX=B AX=B

A , B A,B A,B同时进行初等变换,将 A A A变为对角线都为 1 1 1其他为 0 0 0的矩阵,则此时的 B B B就是 X X X

从第一列开始,每次把 a [ i ] [ i ] = 1 a[i][i]=1 a[i][i]=1,其他变为 0 0 0

流程

  • 从第一列开始。
  • 对每列 i i i [ i , n ] [i,n] [i,n]找到最大的 a [ j ] [ i ] , j ∈ [ i , n ] a[j][i],j\\in [i,n] a[j][i],j[i,n],这里从 i i i开始是因为 [ 1 , i − 1 ] [1,i-1] [1,i1] 1 1 1已经构造好了,不能在进行两行交换破坏结构。
  • 如果此时最大值 a [ i ] [ i ] = 0 a[i][i]=0 a[i][i]=0说明该列都为 0 0 0无解。
  • 否则用该行去抵消其他行,使得该行的非 i i i列都为 0 0 0

时间复杂度: O ( n 3 ) O(n^3) O(n3)

P3389 code

int n;
double a[N][N];
void Gauss(){ //O(n^3)
	rep(i,1,n){
		int mx=i;
		rep(j,i+1,n){
			if(fabs(a[j][i])>fabs(a[mx][i])) mx=j;
		}
		rep(j,1,n+1) swap(a[i][j],a[mx][j]);
		if(!a[i][i]) return (void)puts("No Solution");
		rep(j,1,n){
			if(j!=i){
				double x=a[j][i]/a[i][i];
				rep(k,i+1,n+1)
					a[j][k]-=x*a[i][k];
			}
		}
	}
	rep(i,1,n) printf("%.2f\\n",a[i][n+1]/a[i][i]);
}
int main(){
	scanf("%d",&n);
	rep(i,1,n)
		rep(j,1,n+1) scanf("%lf",&a[i][j]);
	Gauss();
	return 0;
}

法2 高斯消元(回代)

与法1不同的是,该方法没有化为对角为1的矩阵,而是逐个带入消元,最终求得 a n s n ans_n ansn,然后往回代,倒着求出 a n s n − 1 , a n s n − 2 … , a 1 ans_{n-1},ans_{n-2}\\dots,a_1 ansn1,ansn2,a1

int n;
double a[N][N],ans[N];
void Gauss(){ //O(n^3)
	rep(i,1,n){
		int mx=i;
		rep(j,i+1,n){
			if(fabs(a[j][i])>fabs(a[mx][i])) mx=j;
		}
		if(mx!=i) swap(a[mx],a[i]);
		if(!a[i][i]) return (void)puts("No Solution");
		double x=a[i][i];
		rep(j,i,n+1) a[i][j]/=x;
		rep(j,i+1,n){
			x=a[j][i];
			rep(k,i,n+1) a[j][k]-=a[i][k]*x;
		}
	}
	ans[n]=a[n][n+1];
	per(i,n-1,1){	//回代
		ans[i]=a[i][n+1];
		rep(j,i+1,n)
			ans[i]-=a[i][j]*ans[j];
	}
	rep(i,1,n) printf("%.2f\\n",ans[i]);
}
int main(){
	scanf("%d",&n);
	rep(i,1,n)
		rep(j,1,n+1) scanf("%lf",&a[i][j]);
	Gauss();
	return 0;
}

矩阵求逆

同样是利用高斯-约旦消元.

A A − 1 = E AA^{-1}=E AA1=E

构造矩阵 [ A E ] [AE] [AE] ,通过初等变换为: [ E A − 1 ] [EA^{-1}] [EA1].

时间复杂度: O ( n 3 ) O(n^3) O(n3)

code

int n;
ll a[N][N];
ll ksm(ll a,ll n,ll m=mod){
	ll ans=1;
	while(n){
		if(n&1) ans=ans*a%m;
		a=a*a%m;
		n>>=1;
	}
	return ans;
}
void Inv_Matrix(){	//O(n^3)
	int m=n<<1;
	rep(i,1,n){
		int mx=i;
		rep(j,i+1,n){
			if(a[j][i]>a[mx][i]) mx=j;
		}
		if(i!=mx) swap(a[i],a[mx]);
		if(!a[i][i]) return (void)puts("No Solution");
		ll x=ksm(a[i][i],mod-2);
		rep(j,1,n){
			if(j!=i){
				ll y=a[j][i]*x%mod;
				rep(k,i+1,m)
					(a[j][k]-=y*a[i][k]%mod)%=mod;
			}
		}
		rep(j,1,m)  a[i][j]=a[i][j]*x%mod;
	}
	rep(i,1,n){
		rep(j,n+1,m) printf("%lld ",(a[i][j]%mod+mod)%mod);
	printf("\\n");
	} 
}
int main(){
	scanf("%d",&n);
	rep(i,1,n){
		rep(j,1,n) scanf("%lld",&a[i][j]);
		a[i][i+n]=1;
	}
	Inv_Matrix();
	return 0;
}

高斯消元判断是否多解,无解,唯一解

利用传统的高斯消元即可.

时间复杂度: O ( n 3 ) O(n^3) O(n3)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=55,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define x first
#define y second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define ios ios::sync_with_stdio(false),cin.tie(0) 
void Print(int *a,int n){
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\\n",a[n]); 
}
int n;
const double eps=1e-6;
double a[N][N],ans[N];
int Gauss(){ //O(n^3)
	int r=1;
	rep(i,1,n){
		int mx=r;
		rep(j,r+1,n){
			if(fabs(a[j][i])>fabs(a[mx][i])) mx=j;
		}
		if(fabs(a[mx][i])<eps) continue;
		if(mx!=r) swap(a[mx],a[r]);
		double x=a[r][i];
		rep(j,i,以上是关于高斯消元法的主要内容,如果未能解决你的问题,请参考以下文章

luogu P3389 模板高斯消元法

高斯消元法

高斯消元法

高斯消元法

高斯消元法

高斯消元总结