高斯消元(解线性方程组 or 线性同余方程组)

解线性方程组或线性同余方程组。陪队友写了 1 天,挺爽的。

目前还没有考虑 无关变元 的情况,注释部分包括同余和不同余写法,而且只适用于系数是整数且不要太大的情况。double型的还没写,先不写了。

#include <string>
#include <stdio.h>
#include <string.h>
#include <algorithm>

using namespace std;

const int N = 105;
const int mod = 2;
const double eps = 1e-8;

int GCD;

int gcd(int a,int b){
    return b ? gcd(b,a%b) : a;
}

int lcm(int a,int b){
    return a / gcd(a,b) * b;
}

void exgcd(int a,int b,int &x,int &y){
    if(b == 0){
        x = 1; y = 0; GCD = a;
        return ;
    }
    exgcd(b,a%b,x,y);
    int t = x; x = y; y = t - a/b*y;
}

struct Linear{
    int R,C,var;
    int m[N][N];
    int ans[N];
    bool free[N];
    Linear(){
        memset(free,false,sizeof(free));
    }
    Linear(int r,int c):R(r),C(c){
        memset(free,false,sizeof(free));
    }
    bool change(int r,int c){
        int rr = r;
        for(int i=r+1;i<R;i++)
            /*if int*/
            if(abs(m[i][c]) > abs(m[rr][c]))
                rr = i;
        if(rr != r){
            memcpy(m[N-1],m[r],sizeof(m[r]));
            memcpy(m[r],m[rr],sizeof(m[r]));
            memcpy(m[rr],m[N-1],sizeof(m[r]));
        }
        return m[r][c] != 0;
    }
    void op(int r,int c){
        /*if normal int*/
        for(int i=r+1;i!=R;i++){
            if(m[i][c] == 0)
                continue;
            int Lcm = ::lcm(m[r][c],m[i][c]);
            int mult1 = abs(Lcm / m[r][c]);
            int mult2 = abs(Lcm / m[i][c]);
            if(m[r][c]>0 && m[i][c]<0 || m[r][c]<0 && m[i][c]>0)
                mult1 = - mult1;
            for(int j=c;j<=C;j++){
                /*if normal*/
                m[i][j] = m[i][j] * mult2 - m[r][j] * mult1;
                /*if mod*/
                //m[i][j] = ((m[i][j] * mult2 - m[r][j] * mult1) % mod + mod) % mod;
            }
        }
        /*if double*/
        //for(int i=0;i<R;i++){
        //    if(i == r || fabs(m[i][c]) < eps)
        //        continue;
        //    double mult = m[i][c] / m[r][c];
        //    for(int j=c;j<=C;j++)
        //        m[i][j] -= mult * m[r][j];
        //}
    }
    void gauss(){
        int curC = 0;
        for(int curR=0;curR<R && curC<C;curC++){
            if(change(curR,curC)){
                op(curR,curC);
                curR++;
            }
            else{
                free[curC] = true;
                continue;
            }
        }
        /*if int*/
        //deal();
        /*if double*/
        //for(int i=0;i<R;i++)
        //    ans[i] = m[i][C] / m[i][i];
    }
    bool allzero(int r){
        for(int j=C-1;j>=0;j--)
            if(m[r][j] != 0)
                return false;
        return true;
    }
    void deal(){
        for(int i=R-1;i>=0;i--){
            if(allzero(i)){
                if(m[i][C]){
                    var = -1;
                    break;
                }
            }
            else{
                var = C - (i+1);
                break;
            }
        }
        if(var == -1)
            return ;
        for(int mask=0;mask<(1<<var);mask++){
            int ith = 0;
            for(int curR=C-var-1,curC=C-1;curR>=0 && curC>=0;curC--){
                if(free[curC]){
                    ans[curC] = mask >> ith & 1;
                    ith++;
                }
                else{
                    int sum = m[curR][C];
                    for(int j=curC+1;j<C;j++)
                        sum -= m[curR][j] * ans[j];
                    curR--;
                    /*if normal*/
                    //ans[curC] = sum / m[curR][curC];  //if  'm[r][c]' can divide 'sum'.
                    /*if mod*/
                    //sum = (sum % mod + mod) % mod;
                    //int y;exgcd(m[curR][curC],mod,ans[curC],y);
                    //ans[curC] *= sum / GCD;           //if 'GCD' can divide 'sum'.
                    //ans[curC] %= mod;
                    /*if mod 2*/
                    //ans[curC] = sum & 1;
                }
            }
        }
    }
    void init(){
        scanf("%d%d",&R,&C);
        for(int i=0;i<R;i++)
            for(int j=0;j<=C;j++)
                scanf("%lf",&m[i][j]);
    }
    void debug(){
        puts(" *** ");
        for(int i=0;i<R;puts(""),i++)
            for(int j=0;j<=C;j++)
                printf("%7.2f",m[i][j]);
        puts("*****");
    }
    void printans(){
        for(int i=0;i<C;i++)
            printf("%5.2f%c",ans[i],i==C-1?'\n':' ');
    }
};


你可能感兴趣的:(高斯消元(解线性方程组 or 线性同余方程组))