2013-team4/code/gauss

从 Trac 迁移的文章

这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。

原文章内容如下:

{{{
//高斯消元法解异或方程组,将Z2替换成包含需要的运算的域(Field)就可以解其他方程组(模素数的同余方程组)
#include <vector>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cassert>
using namespace std;

class Z2 {
public:
    int v;
    Z2(int x){if(x)v=1;else v=0;}
    Z2(long long x){if(x)v=1; else v=0;}
    Z2(){v=0;}
    Z2(const Z2 &x):v(x.v){}
    void print()const{
        printf("%2d",v);
    }
} ZERO(0);

inline Z2 operator+(const Z2 &a, const Z2 &b){
    return a.v ^ b.v;
}
inline Z2 operator-(const Z2 &x){
    return x;
}
inline Z2 operator-(const Z2 &a, const Z2 &b){
    return a.v ^ b.v;
}
inline Z2 operator*(const Z2 &a, const Z2 &b){
    return a.v & b.v;
}
inline Z2 operator*=(Z2 &a, const Z2 &b){
    return a = a * b;
}
inline Z2 operator+=(Z2 &a, const Z2 &b){
    return a = a + b;
}
inline int sgn(Z2 x){
    return x.v ? 1 : 0;
}
inline Z2 operator/(const Z2 &a, const Z2 &b){
    assert(b.v); //除数非零
    return a.v;
}
inline bool operator<(const Z2 &a, const Z2 &b){
    return a.v < b.v;
}
typedef Z2 Num;

/*
const int p=23;
class modp{
public:
    int v;
    modp(int x){v=x%p;}
    modp(){v=0;}
    modp(const modp &x):v(x.v){}
    void print()const{printf("%3d",v);}
} ZERO(0), ONE(1);
inline modp operator+(const modp &a, const modp &b){
    return (a.v + b.v) % p;
}
inline modp operator-(const modp &x){
    return (-x.v + p) % p;
}
inline modp operator-(const modp &a, const modp &b){
    return (a.v - b.v + p) % p;
}
inline modp operator*(const modp &a, const modp &b){
    return (a.v * b.v) % p;
}
inline modp operator*=(modp &a, const modp &b){
    return a = a * b;
}
inline modp operator^(const modp &a, int n)
{
    modp t(a), res(ONE);
    for(; n; n>>=1, t*=t)
        if(n&1)res*=t;
    assert((res.v*a.v)%p==1);
    return res;
}
inline modp operator+=(modp &a, const modp &b){
    return a = a + b;
}
inline int sgn(modp x){
    return x.v ? 1 : 0;
}
inline modp operator/(const modp &a, const modp &b){
    assert(b.v); //除数非零
    return a * (b ^ (p-2));
}
inline bool operator<(const modp &a, const modp &b){
    return a.v < b.v;
}
typedef modp Num;
*/

typedef vector<Num> VN;
typedef vector<VN> VVN;
#define REP(i,n) for(int i=0; i<int(n); i++)
#define eps 1e-10
inline int sgn(double x){
    if(fabs(x) < eps)return 0;
    else return x > 0 ? 1 : -1;
}

class Matrix{
public:
    VVN v;
    vector<size_t> f; //records the position of the first one in a row, -1 means all zeros
    VN x; //answer to solve 
    VN &operator[](size_t i){return v[i];}
    Matrix(size_t n, size_t m, bool one=0){
        v=VVN(n,VN(m,0));
        if(one){
            int nn=min(n,m);
            REP(i, nn)v[i][i]=1;
        }
    }
    Matrix(const VVN &d):v(d){}
    Matrix(const Matrix &A):v(A.v){}

    size_t size() const {return v.size();}

    void print(void) const {
        for(size_t i = 0; i < v.size(); i++){
            for(size_t j = 0; j < v[i].size(); j++)
                v[i][j].print();
            printf("\n");
        }
    }

    void swapRow(size_t i, size_t j){swap(v[i], v[j]);}
    void mulRow(size_t i, Num times){REP(j, v[i].size())v[i][j] *= times;}
    //add times*Row i to row j
    void addMulRow(Num times, size_t i, size_t j)
    {REP(k,v[i].size())v[j][k]+=v[i][k]*times;}

    void toEchelonForm(){
        if(v.size()==0)return;
        f.clear();
        int n=v.size(), m=v[0].size();
        f.resize(n, -1);
        int r=0, c=0; //rth row, cth column
        for(;r<n && c<m; r++, c++){
            Num maxv=v[r][c];
            size_t row=r;
            for(size_t i=r+1; i<n; i++)
                if(maxv < v[i][c])
                    maxv = v[row = i][c];
            if(sgn(maxv)==0){
                r--;
                continue;
            }
            f[r]=c;
            swapRow(r, row);
            for(size_t i=r+1; i<n; i++){
                Num t=-v[i][c]/maxv;
                if(sgn(t))addMulRow(t, r, i);
            }
            mulRow(r, 1/maxv);
        }
    }

    // -1无解, 0唯一解, >=1自由元个数,有解的话x中存某一组解
    int solve(){
        toEchelonForm();
        if(v.size()==0)return 0;
        int n=v.size(), m=v[0].size();
        x.resize(m-1);
        int k=m-2;
        int cnt=0;
        for(int i=n-1; i>=0; i--){
            if(f[i]==-1)continue;
            if(f[i]==m-1)return -1;
            Num sum=v[i][m-1];
            for(int j=m-2; j>k; j--)
                sum=sum - x[j] * v[i][j];
            for(int j=k; j>f[i]; j--)
                x[j]=ZERO, cnt++;
            k=f[i];
            x[k--]=sum;
        }
        for(int j=k; j>=0; j--)
            x[j]=ZERO, cnt++;
        return cnt;
    }
};
}}}
//高斯消元法解异或方程组,将Z2替换成包含需要的运算的域(Field)就可以解其他方程组(模素数的同余方程组)
#include <vector>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cassert>
using namespace std;
class Z2 {
public:
    int v;
    Z2(int x){if(x)v=1;else v=0;}
    Z2(long long x){if(x)v=1; else v=0;}
    Z2(){v=0;}
    Z2(const Z2 &x):v(x.v){}
    void print()const{
        printf("%2d",v);
    }
} ZERO(0);
inline Z2 operator+(const Z2 &a, const Z2 &b){
    return a.v ^ b.v;
}
inline Z2 operator-(const Z2 &x){
    return x;
}
inline Z2 operator-(const Z2 &a, const Z2 &b){
    return a.v ^ b.v;
}
inline Z2 operator*(const Z2 &a, const Z2 &b){
    return a.v & b.v;
}
inline Z2 operator*=(Z2 &a, const Z2 &b){
    return a = a * b;
}
inline Z2 operator+=(Z2 &a, const Z2 &b){
    return a = a + b;
}
inline int sgn(Z2 x){
    return x.v ? 1 : 0;
}
inline Z2 operator/(const Z2 &a, const Z2 &b){
    assert(b.v); //除数非零
    return a.v;
}
inline bool operator<(const Z2 &a, const Z2 &b){
    return a.v < b.v;
}
typedef Z2 Num;
/*
const int p=23;
class modp{
public:
    int v;
    modp(int x){v=x%p;}
    modp(){v=0;}
    modp(const modp &x):v(x.v){}
    void print()const{printf("%3d",v);}
} ZERO(0), ONE(1);
inline modp operator+(const modp &a, const modp &b){
    return (a.v + b.v) % p;
}
inline modp operator-(const modp &x){
    return (-x.v + p) % p;
}
inline modp operator-(const modp &a, const modp &b){
    return (a.v - b.v + p) % p;
}
inline modp operator*(const modp &a, const modp &b){
    return (a.v * b.v) % p;
}
inline modp operator*=(modp &a, const modp &b){
    return a = a * b;
}
inline modp operator^(const modp &a, int n)
{
    modp t(a), res(ONE);
    for(; n; n>>=1, t*=t)
        if(n&1)res*=t;
    assert((res.v*a.v)%p==1);
    return res;
}
inline modp operator+=(modp &a, const modp &b){
    return a = a + b;
}
inline int sgn(modp x){
    return x.v ? 1 : 0;
}
inline modp operator/(const modp &a, const modp &b){
    assert(b.v); //除数非零
    return a * (b ^ (p-2));
}
inline bool operator<(const modp &a, const modp &b){
    return a.v < b.v;
}
typedef modp Num;
*/
typedef vector<Num> VN;
typedef vector<VN> VVN;
#define REP(i,n) for(int i=0; i<int(n); i++)
#define eps 1e-10
inline int sgn(double x){
    if(fabs(x) < eps)return 0;
    else return x > 0 ? 1 : -1;
}
class Matrix{
public:
    VVN v;
    vector<size_t> f; //records the position of the first one in a row, -1 means all zeros
    VN x; //answer to solve 
    VN &operator[](size_t i){return v[i];}
    Matrix(size_t n, size_t m, bool one=0){
        v=VVN(n,VN(m,0));
        if(one){
            int nn=min(n,m);
            REP(i, nn)v[i][i]=1;
        }
    }
    Matrix(const VVN &d):v(d){}
    Matrix(const Matrix &A):v(A.v){}
    size_t size() const {return v.size();}
    void print(void) const {
        for(size_t i = 0; i < v.size(); i++){
            for(size_t j = 0; j < v[i].size(); j++)
                v[i][j].print();
            printf("\n");
        }
    }
    void swapRow(size_t i, size_t j){swap(v[i], v[j]);}
    void mulRow(size_t i, Num times){REP(j, v[i].size())v[i][j] *= times;}
    //add times*Row i to row j
    void addMulRow(Num times, size_t i, size_t j)
    {REP(k,v[i].size())v[j][k]+=v[i][k]*times;}
    void toEchelonForm(){
        if(v.size()==0)return;
        f.clear();
        int n=v.size(), m=v[0].size();
        f.resize(n, -1);
        int r=0, c=0; //rth row, cth column
        for(;r<n && c<m; r++, c++){
            Num maxv=v[r][c];
            size_t row=r;
            for(size_t i=r+1; i<n; i++)
                if(maxv < v[i][c])
                    maxv = v[row = i][c];
            if(sgn(maxv)==0){
                r--;
                continue;
            }
            f[r]=c;
            swapRow(r, row);
            for(size_t i=r+1; i<n; i++){
                Num t=-v[i][c]/maxv;
                if(sgn(t))addMulRow(t, r, i);
            }
            mulRow(r, 1/maxv);
        }
    }
    // -1无解, 0唯一解, >=1自由元个数,有解的话x中存某一组解
    int solve(){
        toEchelonForm();
        if(v.size()==0)return 0;
        int n=v.size(), m=v[0].size();
        x.resize(m-1);
        int k=m-2;
        int cnt=0;
        for(int i=n-1; i>=0; i--){
            if(f[i]==-1)continue;
            if(f[i]==m-1)return -1;
            Num sum=v[i][m-1];
            for(int j=m-2; j>k; j--)
                sum=sum - x[j] * v[i][j];
            for(int j=k; j>f[i]; j--)
                x[j]=ZERO, cnt++;
            k=f[i];
            x[k--]=sum;
        }
        for(int j=k; j>=0; j--)
            x[j]=ZERO, cnt++;
        return cnt;
    }
};