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;
    }
    


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

  • 相关阅读:
    Codeforces 723d [暴力dfs]
    Codeforces 723e [图论][欧拉回路]
    Hihocoder 1035 [树形dp]
    Codeforces 721C [dp][拓扑排序]
    Codeforces 721D [贪心]
    info
    关于string操作
    Floyd求最小环 HDU1599
    Codeforces Round #572 (Div. 2) B Number Circle
    A. XXXXX
  • 原文地址:https://www.cnblogs.com/hqwhqwhq/p/4811896.html
Copyright © 2011-2022 走看看