高斯消元学习笔记
高斯消元学习笔记
其实这个主题能够复活主要还是粘了
求解线性方程组
这个只能说是典中典了,我不相信没有一个人的高斯消元不是从这里开始的。
我们考虑求解线性方程组的本质:将每一个式子所有未知数前都有系数转化成每一个式子只有一个未知数前有系数。那么我们不妨用矩阵来表示这样的关系。
对于线性方程组
我们将其写成
的形式,接着我们考虑消元,为了让整个矩阵最后呈现出
的形式,我们需要:
- 对于枚举到的每一行,将当前行对应的未知数前的系数变为
。 - 将其他行对应此时的未知数前的系数变为
。
最后从下往上,将每个未知数的值回代,求出每个未知数的解。
对于无解或无穷解的判断,主要在于全
代码
int gauss(){
int c,r;
for(c=1,r=1;c<=n;c++){
int t=r;
for(int i=r;i<=n;i++){
if(fabs(a[i][c])>fabs(a[t][c]))t=i;
}
if(fabs(a[t][c])<eps)continue;
for(int i=c;i<=n+1;i++)swap(a[t][i],a[r][i]);
for(int i=n+1;i>=c;i--)a[r][i]/=a[r][c];
for(int i=r+1;i<=n;i++){
if(fabs(a[i][c])>eps){
for(int j=n+1;j>=c;j--)a[i][j]-=a[r][j]*a[i][c];
}
}
r++;//消元
}
if(r<=n){
for(int i=r;i<=n;i++){
if(fabs(a[i][n+1])>eps)return 2;//方程无解
}
return 1;//方程有无穷多组解
}
for(int i=n;i>=1;i--){
for(int j=i+1;j<=n;j++)a[i][n+1]-=a[i][j]*a[j][n+1];
}
return 0;//方程有唯一解
}
求解矩阵逆元
学过矩阵快速幂的都知道,矩阵的单位元
参考整数逆元的定义:如果
那么对于一个矩阵
那么我们对左边的
但是和整数逆元一样,矩阵在有些时候也没有逆元,比如不能成功除以
我们可以考虑矩阵求逆和求解线性方程组的关系,不难发现,如果令
那么有
代码
int gauss(){
for(int i=1;i<=n;i++){
for(int j=i;j<=n;j++){
if(fabs(A[j][i])<=eps)continue;
for(int k=i;k<=(n<<1);k++)swap(A[i][k],A[j][k]);
break;
}
if(fabs(A[i][i])<=eps)return 1;
for(int j=(n<<1);j>=i;j--)A[i][j]/=A[i][i];
for(int j=1;j<=n;j++){
if(i==j)continue;
for(int k=(n<<1);k>=i;k--)A[j][k]-=A[j][i]*A[i][k];
}
}
return 0;
}
求解行列式
对于一个矩阵
对于矩阵
有
其中
- 如果矩阵
是一个上三角矩阵,即 ,那么 。 - 如果矩阵
的某一行同时乘上一个常数 得到矩阵 ,那么 。 - 矩阵
的行列式与矩阵 的转置的行列式相等,即 。 - 如果矩阵
的任意两行互换后得到矩阵 ,那么 。 - 如果矩阵
的其中一行加上另外一行得到矩阵 ,那么 。
不难发现消元的过程符合性质
我们可以考虑行列式和求解线性方程组的关系,根据
给定一个
元线性方程组,其未知数分别记作 。 设其矩阵表示形式为
,其中 为该方程组的增广矩阵, 为由未知数组成的向量, 为由常数项组成的向量, 为 中的第 列被 取代后的矩阵,若 ,则 ;否则该方程组无解。
由此,我们看出求解线性方程组也可以通过这样的方式完成。但是复杂度要更差。
代码
double gauss(){
double res=1;
for(int i=1;i<=n;i++){
for(int j=i;j<=n;j++){
if(fabs(A[j][i])<=eps)continue;
for(int k=i;k<=n;k++)swap(A[i][k],A[j][k]);
if(i!=j)res=-res;
break;
}
if(fabs(A[i][i])<=eps)return 0;
for(int j=i+1;j<=n;j++){
for(int k=n;k>=i;k--)A[j][k]-=A[j][i]/A[i][i]*A[i][k];
}
}
for(int i=1;i<=n;i++)res*=A[i][i];
return res;
}
//下面提供一种模数不为质数的写法
ll gauss(){
ll res=1;
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
while(a[j][i]){
ll div=a[i][i]/a[j][i];
for(int k=i;k<=n;k++)a[i][k]=(a[i][k]-div*a[j][k])%P;
for(int k=i;k<=n;k++)swap(a[i][k],a[j][k]);
res=-res;
}
}
}
for(int i=1;i<=n;i++)res=res*a[i][i]%P;
return res;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?