zoukankan      html  css  js  c++  java
  • 高斯消元小结(贴一些模板)

    依旧是跟着hihocoder学习高斯消元,以前只是知道,并不会写,现在感觉写起来还是比较简单的,其实就是一个线性代数的知识。(我记得今年好像做到过一道高斯消元的题,比较隐蔽的方程组,然后队友最后想到了,然而并没有时间写完,结束以后也并没有补一下高斯消元)。

    高斯消元关键就是一个倒三角形吧,然后判断是无穷解,无解,唯一解的的条件就是矩阵的秩与n(元的个数)的关系:

    n元方程组 Ax = b 解的情况和R(A),R(A,b),n有关。

    无解: R(A) < R(A,b)

    唯一解:R(A) == R(A,b) == n

    无穷解:R(A) == R(A,b) < n

    具体实现方法可以看程序,(然而我觉得hihocoder的伪代码写得很不错)。

    然后是异或方程组,这里有一个很重要的异或公式 a xor b == c 等价于 b == a xor c,其实这里很好理解。

    异或方程可以表示为 初始状态 xor (a[i][1] * x[1]) xor (a[i][2] * x[2]) xor ... xor (a[i][n]*x[n]) == c[i] 这个时候可以转化成:(a[i][1] * x[1]) xor (a[i][2] * x[2]) xor ... xor (a[i][n]*x[n]) == c[i] xor 初始状态。搞定

    异或方程组的消元是利用了 1^1 == 0来做的,但是这个消元的时候要注意,1^0 == 1,也就是在消元的时候不能呆头呆脑地直接搞,遇到这个a[j][i] == 0了,直接跳过就好了。

    下面贴一下模板:

    高斯消元:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <stack>
    #define FOR(i,x,y)  for(int i = x;i < y;i ++)
    #define IFOR(i,x,y) for(int i = x;i > y;i --)
    #define ll long long
    #define N 550
    #define M 1100
    
    using namespace std;
    
    const double eps = 1e-6;
    
    int n,m;
    double a[M][N],c[M],b[N],val[N];
    
    
    bool zero(double x){
        return fabs(x) < eps;
    }
    
    void swap(int i,int j){
        FOR(k,1,n+1){
            b[k] = a[i][k];
            a[i][k] = a[j][k];
            a[j][k] = b[k];
        }
        double tem = c[i];
        c[i] = c[j];
        c[j] = tem;
    }
    
    int guass(){
        bool manysolution = false;
        FOR(i,1,n+1){
            bool flag = false;
            FOR(j,i,m+1){
                if(!zero(a[j][i])){
                    swap(i,j);
                    flag = true;
                    break;
                }
            }
            if(!flag){
                manysolution = true;
                continue;
            }
            FOR(j,i+1,m+1){
                double tem = a[j][i]/a[i][i];
                FOR(k,i,n+1){
                    a[j][k] = a[j][k] - a[i][k]*tem;
                }
                c[j] = c[j] - c[i]*tem;
            }
        }
        FOR(i,1,m+1){
            bool flag = true;
            FOR(j,1,n+1){
                if(!zero(a[i][j])){
                    flag = false;
                    break;
                }
            }
            if(flag && !zero(c[i])){
                return -1;
            }
        }
        if(manysolution)
            return 1;
        IFOR(i,n,0){
            FOR(j,1,i){
                double tem = a[j][i]/a[i][i];
                FOR(k,1,n+1){
                    a[j][k] = a[j][k] - a[i][k]*tem;
                }
                c[j] = c[j] - c[i]*tem;
            }
            val[i] = c[i]/a[i][i];
        }
        return 0;
    }
    
    int main()
    {
        //freopen("test.in","r",stdin);
        while(~scanf("%d%d",&n,&m)){
            FOR(i,1,m+1){
                FOR(j,1,n+1)
                    scanf("%lf",&a[i][j]);
                scanf("%lf",&c[i]);
            }
            int tem = guass();
            if(tem == -1)   printf("No solutions
    ");
            else if(tem == 1) printf("Many solutions
    ");
            else{
                FOR(i,1,n+1){
                    printf("%d
    ",(int)(val[i]+eps));
                }
            }
        }
        return 0;
    }
    

    异或方程组:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #define ll long long
    #define FOR(i,x,y)  for(int i = x;i < y;i ++)
    #define IFOR(i,x,y) for(int i = x;i > y;i --)
    #define N 35
    
    using namespace std;
    
    const double eps = 1e-6;
    
    char str[10];
    
    int a[N][N],c[N],val[N],ans[N];
    
    void init(){
        FOR(i,0,30) c[i] = c[i] ^ 1;
        memset(a,0,sizeof(a));
        FOR(i,0,30){
            int u = i / 6, v = i % 6;
            a[i][i] = 1;
            int nu,nv;
            nu = u-1;nv = v;
            if(nu >= 0 && nu < 5 && nv >= 0 && nv < 6)  a[i][nu*6+nv] = 1;
            nu = u+1;nv = v;
            if(nu >= 0 && nu < 5 && nv >= 0 && nv < 6)  a[i][nu*6+nv] = 1;
            nu = u;nv = v-1;
            if(nu >= 0 && nu < 5 && nv >= 0 && nv < 6)  a[i][nu*6+nv] = 1;
            nu = u;nv = v+1;
            if(nu >= 0 && nu < 5 && nv >= 0 && nv < 6)  a[i][nu*6+nv] = 1;
        }
    }
    
    void swap(int i,int j){
        FOR(k,0,30){
            int tem = a[i][k];
            a[i][k] = a[j][k];
            a[j][k] = tem;
        }
        int tem = c[i];
        c[i] = c[j];
        c[j] = tem;
    }
    
    int guass(){
        bool manysolutions = false;
        FOR(i,0,30){
            bool flag = false;
            FOR(j,i,30){
                if(a[j][i]){
                    swap(i,j);
                    flag = true;
                    break;
                }
            }
            FOR(j,i+1,30){
                if(!a[j][i]) continue;
                FOR(k,0,30){
                    a[j][k] = a[i][k] ^ a[j][k];
                }
                c[j] = c[i] ^ c[j];
            }
            if(!flag){
                manysolutions = true;
            }
        }
        FOR(i,0,30){
            int flag = true;
            FOR(j,0,30){
                if(a[i][j]) flag = false;
            }
            if(flag && c[i])    return -1;
        }
        if(manysolutions)   return 1;
        IFOR(i,29,-1){
            FOR(j,0,i){
                if(!a[j][i]) continue;
                FOR(k,0,30){
                    a[j][k] = a[i][k] ^ a[j][k];
                }
                c[j] = c[j] ^ c[i];
            }
            val[i] = c[i];
        }
        return 0;
    }
    
    int main()
    {
        //freopen("test.in","r",stdin);
        while(~scanf("%s",str)){
            FOR(i,0,6){
                c[i] = str[i] - '0';
            }
            FOR(i,1,5){
                scanf("%s",str);
                FOR(j,0,6){
                    c[i*6+j] = str[j] - '0';
                }
            }
            memset(val,0,sizeof(val));
            init();
            guass();
            int cnt = 0;
            FOR(i,0,30){
                if(val[i])  ans[cnt++] = i;
            }
            printf("%d
    ",cnt);
            FOR(i,0,cnt){
                printf("%d %d
    ",(ans[i]/6)+1,(ans[i]%6)+1);
            }
        }
        return 0;
    }
    


    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    js截取字符串区分汉字字母代码
    List 去处自定义重复对象方法
    63. Unique Paths II
    62. Unique Paths
    388. Longest Absolute File Path
    41. First Missing Positive
    140. Word Break II
    139. Word Break
    239. Sliding Window Maximum
    5. Longest Palindromic Substring
  • 原文地址:https://www.cnblogs.com/hqwhqwhq/p/4811896.html
Copyright © 2011-2022 走看看