解线性方程组或线性同余方程组。陪队友写了 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':' '); } };