高斯消元

1.高斯消元
在O(n^3)下求解一个包含n个方程组n个未知数的多元线性方程组

n元线性方程组解的三种情况:无穷多组解、唯一解、无解

对n*(n+1)的增广矩阵做初等行列变换:
1.把某一行乘以一个非零的数
2. 交换某两行
3. 把某行的若干倍加到另一行

如果出现:
1.r(A)=n,即最后的阶梯型恰好是由n个方程式构成的(完美阶梯型n个方程n个未知数)唯一解
2.出现一个方程 0=k (k≠0) 无解
3.出现一些0=0的方程(说明这个方程可以由别的方程表示,是多余的) 无穷多个解

算法步骤:
1.枚举每一列c
 (1)找到这一列绝对值最大的那一行
 (2)将这一行换到当前未处理的最上面
 (3)将该行的第一个数变成1
 (4)将下面所有行的第c列消成0
在这里插入图片描述
2.消成阶梯型后,判断解的情况,若有唯一解,从下往上带入(消除)求解。

例题1 解线性方程组

在这里插入图片描述

输入
3
1.00 2.00 -1.00 -6.00
2.00 1.00 -3.00 -9.00
-1.00 -1.00 2.00 7.00
输出
1.00
-2.00
3.00
代码
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn=110;
const double eps=1e-7;
int n;
double a[maxn][maxn];
int gauss()
{
    int c,r;
    for(c=0,r=0;c<n;c++)//遍历每一列
    {
        int t=r;//t中存放当前最大值所在那一行行标
        for(int i=r;i<n;i++)
            if(fabs(a[i][c])>fabs(a[t][c]))
                t=i;
        if(fabs(a[t][c])<eps)//最大值等于0
            continue;//说明该列全为0,换下一列进行比较
        
        //交换两行
        for(int i=c;i<n+1;i++)//共有n+1列
            swap(a[t][i],a[r][i]);
        //把那个最大值变为1
        for(int i=n;i>=c;i--)//这里应该从后往前,因为那个最大值必须最后一个除,不然会变成都除1
            a[r][i]/=a[r][c];//r是当前的最上层
        //把该列下面的值都消成0
        for(int i=r+1;i<n;i++)
            if(fabs(a[i][c])>eps)
                for(int j=n;j>=c;j--)
                    a[i][j]-=a[r][j]*a[i][c];
        r++;
    }
    if(r<n)//有左部全为0的行
    {
        for(int i=r;i<n;i++)
            if(fabs(a[i][n])>eps)//右部不为0
                return 2;//无解
        return 1;//有0=0,无穷多组解
    }
    //有唯一解,从下往上消
    for(int i=n-1;i>=0;i--)//处理每一行
        for(int j=i+1;j<n;j++)//用下面那层消上面那层
            a[i][n]-=a[j][n]*a[i][j];//系数是上面那行要被消掉的值a[i][j]

    return 0;
}
int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
        for(int j=0;j<n+1;j++)
            cin>>a[i][j];
    int flag=gauss();

    if(flag==0)
    {
        for(int i=0;i<n;i++)
        printf("%.2lf\n",a[i][n]);
    }else if(flag==1)
        cout<<"Infinite group solutions"<<endl;
    else
        cout<<"No solution"<<endl;
    return 0;
}
例题2 解异或线性方程组

异或也是不进位的加法
在这里插入图片描述

输入
3
1 1 0 1
0 1 1 0
1 0 0 1
输出
1
0
0
代码

基本差不多,不过运算从加减乘除变成了异或、与之类的。

#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=105;
const int mod=1e9+7;
int n;
int a[maxn][maxn];
int gauss()
{
    int c,r;
    for(c=0,r=0;c<n;c++)//遍历每一列
    {
        int t=r;//从当前未处理的行开始
        for(int i=r;i<n;i++)
            if(a[i][c])
                t=i;
        if(!a[t][c])//如果该列没有1,换着处理下一列
            continue;
        
        for(int i=c;i<=n;i++)
            swap(a[r][i],a[t][i]);
        for(int i=r+1;i<n;i++)//消除下面其他行的1
            if(a[i][c])
            {
                for(int j=n;j>=c;j--)
                a[i][j]^=a[r][j];//两个1异或就变成0了,注意不能用减,不然0-1会出现-1
            }
        r++;
    }
    if(r<n)
    {
        for(int i=r;i<n;i++)
            if(a[i][n])
                return 2;
        return 1;
    }
    for(int i=n-1;i>=0;i--)//从下往上迭代
        for(int j=i+1;j<n;j++)//i=n-1,任何数和0异或都是它本身
            a[i][n]^=a[i][j]&a[j][n];//系数a[i][j],或者用*代替咯
    return 0;
}
int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
        for(int j=0;j<n+1;j++)
            cin>>a[i][j];
    int flag=gauss();
    if(flag==0)
    {
        for(int i=0;i<n;i++)
            cout<<a[i][n]<<endl;
    }else if(flag==1)
        cout<<"Multiple sets of solutions"<<endl;
    else
        cout<<"No solution"<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值