zoukankan      html  css  js  c++  java
  • 高斯消元简析

    想必大家都可以非常迅速的解出一个二元一次方程组,

    那么三元呢(这也还好),那么再多一些未知数?

    于是这里就要介绍到高斯消元的方法了...

    本人蒟蒻到现在才学高斯消元,请不要介意方法过于垃圾

     --------------------------------------------------------------------------------------------------

    首先假设你拿到了一个n元方程组,那么它应该有n个方程,每个方程有n+1个系数,

    好于是我们把他们全部弄到一个n*(n+1)的矩阵中,这里简称为系数矩阵

    第一步:我们先把每一行的系数都除以这一行的第一个数

    第二步:从第一行到第n行分别控制x1...xn的解,因此你需要把第i行的第i列的系数化为1以此来求解方程,

    第三步:在处理第i行的时候,把第i+1行到第n行的数通过加减消元法处理

       

    第四步:那么求出这个答案就是最后的答案数组了,

    求答案是xn的值是a[n][n+1],然后如果求x(n-1)的值就是将xn的值代入a[n-1][n],然后求出x(n-1)的值

    于是乎 x1=-1,x2=3,x3=-6

    以上就是关于高斯消元简要的介绍.

    下面是两种不同题目下的高斯消元

    (1) 方程保证是整数解,且系数大小均为long long 以内

    注意:此处运用到简单的高精度,以及取模

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<cmath>
     5 #include<algorithm>
     6 #define ll long long
     7 using namespace std;
     8 const ll p=1000000000000000009;
     9 ll a[210][210],ans[210];
    10 ll mul(ll a,ll b){return (__int128)a*b%p;}
    11 ll inv(ll a){
    12     ll res=1,b=p-2;
    13     while (b){
    14         if (b&1) res=mul(res,a); b>>=1; a=mul(a,a);
    15     } return res;
    16 }
    17 ll Div(ll a,ll b){return mul(a,inv(b));}
    18 ll read(){
    19     char ch[1010]; scanf("%s",ch+1);
    20     ll res=0,len=strlen(ch+1);
    21     for (int i=1;i<=len;++i){
    22         res=mul(res,10)+ch[i]-'0';
    23         if (res>p) res-=p;
    24     }
    25     return res;
    26 }
    27  
    28  
    29 int main() {
    30     int n;scanf("%d",&n);
    31     for(int i=1;i<=n;i++){
    32         for(int j=1;j<=n;j++)
    33             scanf("%lld",&a[i][j]);
    34         a[i][n+1]=read();
    35         ll res=a[i][1];
    36         for(int j=1;j<=n+1;j++) a[i][j]=Div(a[i][j],res);
    37     }
    38     for(int i=1;i<=n;i++){
    39         if (a[i][i]==0) {puts("zzylihai"); return 0;}
    40         for(int j=i+1;j<=n+1;++j)
    41             a[i][j]=Div(a[i][j],a[i][i]);
    42         a[i][i]=1;
    43         for(int j=i+1;j<=n;j++) {
    44             for(int k=i+1;k<=n+1;k++){
    45                 a[j][k]-=mul(a[j][i],a[i][k]);
    46                 if (a[j][k]<0) a[j][k]+=p;
    47             }
    48             a[j][i]=0;
    49         }
    50     }
    51     for(int i=n;i>=1;i--) {
    52         ll res=a[i][n+1];
    53         for(int j=i+1;j<=n;j++) {
    54             res-=mul(ans[j],a[i][j]);
    55             if (res<0) res+=p;
    56         }
    57         ans[i]=Div(res,a[i][i]);
    58     }
    59     for(int i=1;i<=n;i++) printf("%lld
    ",ans[i]);
    60     return 0;
    61 }
    View Code

    (2)方程为实数解,要判断是否无解

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    double a[210][210],ans[210];
    int n;
    int main() {
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n+1;j++)
                scanf("%lf",&a[i][j]),a[i][j]*=1.00;
            double res=a[i][1];
            for(int j=1;j<=n+1;j++)
                a[i][j]=(double)a[i][j]/res;
        }
        for(int i=1;i<=n;i++){
            if (a[i][i]==0) {puts("No solution"); return 0;}
            for(int j=i+1;j<=n+1;++j)
                a[i][j]/=a[i][i];
            a[i][i]=1;
            for(int j=i+1;j<=n;j++) {
                for(int k=i+1;k<=n+1;k++)
                    a[j][k]-=a[j][i]*a[i][k];
                a[j][i]=0;
            }
        }
        for(int i=n;i>=1;i--) {
            double res=a[i][n+1];
            for(int j=i+1;j<=n;j++) res-=ans[j]*a[i][j];
            ans[i]=res/a[i][i];
        }
        for(int i=1;i<=n;i++) printf("%.0lf
    ",ans[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    HDU 5744
    HDU 5815
    POJ 1269
    HDU 5742
    HDU 4609
    fzu 1150 Farmer Bill's Problem
    fzu 1002 HangOver
    fzu 1001 Duplicate Pair
    fzu 1150 Farmer Bill's Problem
    fzu 1182 Argus 优先队列
  • 原文地址:https://www.cnblogs.com/logic-yzf/p/7695115.html
Copyright © 2011-2022 走看看