\[\begin{cases} 2x + 3y = 8 \\ x - y = 1 \end{cases}\]
Cách bạn làm ở phổ thông: từ phương trình 2, \(x = y + 1\), thế vào phương trình 1: \(2(y+1) + 3y = 8 \Rightarrow 5y = 6 \Rightarrow y = 1.2\), \(x = 2.2\). Khử Gauss là phiên bản máy móc của thao tác "thế" này cho hệ \(n\) ẩn: dùng hàng này triệt tiêu 1 ẩn ở các hàng khác, lặp lại đến khi ma trận thành dạng bậc thang thì đọc nghiệm. Mọi định thức, nghịch đảo, rank (§2–§4) đều chỉ là "sản phẩm phụ" của cùng một quá trình khử.
Biến đổi ma trận augmented \([A | b]\) thành dạng bậc thang (row echelon form) bằng các phép biến đổi hàng:
- Hoán đổi 2 hàng
- Nhân hàng với hằng số khác 0
- Cộng bội của hàng này vào hàng khác
constlonglongMOD=1e9+7;// Lũy thừa modulo (MOD nguyên tố)longlongmodPow(longlonga,longlonge){longlongr=1;while(e){if(e&1)r=r*a%MOD;a=a*a%MOD;e>>=1;}returnr;}// Giải hệ phương trình tuyến tính modulo MOD// Trả về nghiệm hoặc rỗng nếu vô nghiệm/vô số nghiệmvector<longlong>gaussianElimination(vector<vector<longlong>>a,vector<longlong>b){intn=a.size();intm=a[0].size();// Tạo ma trận augmented (giữ bản sao a0, b0 để kiểm tra nghiệm sau này)vector<vector<longlong>>a0=a;vector<longlong>b0=b;vector<vector<longlong>>aug(n,vector<longlong>(m+1));for(inti=0;i<n;i++){for(intj=0;j<m;j++)aug[i][j]=a[i][j];aug[i][m]=b[i];}vector<int>where(m,-1);for(intcol=0,row=0;col<m&&row<n;col++){// Tìm pivot: hàng đầu tiên có phần tử khác 0 (mod MOD) ở cột col// (Với số học modulo, so sánh abs/1e-9 là vô nghĩa — chỉ cần != 0)intsel=-1;for(inti=row;i<n;i++){if((aug[i][col]%MOD+MOD)%MOD!=0){sel=i;break;}}if(sel==-1)continue;// cột toàn 0 → bỏ qua// Hoán đổi hàngswap(aug[sel],aug[row]);where[col]=row;// Khử cộtlonglonginv=modPow(aug[row][col],MOD-2);for(inti=0;i<n;i++){if(i!=row){longlongfactor=aug[i][col]*inv%MOD;for(intj=col;j<=m;j++){aug[i][j]=(aug[i][j]-factor*aug[row][j]%MOD+MOD)%MOD;}}}row++;}// Lấy nghiệmvector<longlong>x(m,0);for(inti=0;i<m;i++){if(where[i]!=-1){x[i]=aug[where[i]][m]*modPow(aug[where[i]][i],MOD-2)%MOD;}}// Kiểm tra vô nghiệm trên ma trận GỐC (aug đã bị biến đổi)for(inti=0;i<n;i++){longlongsum=0;for(intj=0;j<m;j++)sum=(sum+x[j]*a0[i][j])%MOD;if((sum-b0[i]%MOD+MOD)%MOD!=0)return{};// Vô nghiệm}returnx;}
MOD=10**9+7defgaussian_elimination(a,b):n=len(a)m=len(a[0])a0=[row[:]forrowina]# giữ bản gốc để kiểm tra nghiệmb0=b[:]aug=[a[i][:]+[b[i]]foriinrange(n)]where=[-1]*mcol,row=0,0whilecol<mandrow<n:# Tìm pivot: hàng đầu tiên có phần tử != 0 (mod MOD)sel=-1foriinrange(row,n):ifaug[i][col]%MOD!=0:sel=ibreakifsel==-1:col+=1continueaug[sel],aug[row]=aug[row],aug[sel]where[col]=rowinv=pow(aug[row][col],MOD-2,MOD)foriinrange(n):ifi!=row:factor=aug[i][col]*inv%MODforjinrange(col,m+1):aug[i][j]=(aug[i][j]-factor*aug[row][j]%MOD+MOD)%MODrow+=1col+=1x=[0]*mforiinrange(m):ifwhere[i]!=-1:x[i]=aug[where[i]][m]*pow(aug[where[i]][i],MOD-2,MOD)%MOD# Kiểm tra vô nghiệm trên ma trận GỐCforiinrange(n):s=sum(x[j]*a0[i][j]forjinrange(m))%MODif(s-b0[i]+MOD)%MOD!=0:returnNonereturnx
longlongmodPow(longlonga,longlonge){constlonglongMOD=1e9+7;longlongr=1;while(e){if(e&1)r=r*a%MOD;a=a*a%MOD;e>>=1;}returnr;}longlongdeterminant(vector<vector<longlong>>a){intn=a.size();constlonglongMOD=1e9+7;longlongdet=1;for(intcol=0;col<n;col++){// Tìm pivot != 0 (mod MOD)intsel=-1;for(introw=col;row<n;row++){if((a[row][col]%MOD+MOD)%MOD!=0){sel=row;break;}}if(sel==-1)return0;// cột toàn 0 → định thức = 0if(sel!=col){swap(a[sel],a[col]);det=(MOD-det)%MOD;// đổi hàng → nhân -1}det=det*a[col][col]%MOD;// nhân chéo chính vào định thứclonglonginv=modPow(a[col][col],MOD-2,MOD);// Khử các hàng dưới (không cần chuẩn hóa hàng pivot vì det đã nhân)for(introw=col+1;row<n;row++){longlongfactor=a[row][col]*inv%MOD;for(intj=col;j<n;j++){a[row][j]=(a[row][j]-factor*a[col][j]%MOD+MOD)%MOD;}}}returndet;}
longlongmodPow(longlonga,longlonge){constlonglongMOD=1e9+7;longlongr=1;while(e){if(e&1)r=r*a%MOD;a=a*a%MOD;e>>=1;}returnr;}// Trả về ma trận nghịch đảo hoặc ma trận rỗng nếu không khả nghịchvector<vector<longlong>>inverseMatrix(vector<vector<longlong>>a){intn=a.size();constlonglongMOD=1e9+7;// Tạo augmented [A | I]vector<vector<longlong>>aug(n,vector<longlong>(2*n,0));for(inti=0;i<n;i++){for(intj=0;j<n;j++)aug[i][j]=a[i][j];aug[i][n+i]=1;}// Khử Gaussfor(intcol=0;col<n;col++){// Tìm pivot != 0 (mod MOD)intsel=-1;for(introw=col;row<n;row++){if((aug[row][col]%MOD+MOD)%MOD!=0){sel=row;break;}}if(sel==-1)return{};// Không khả nghịchswap(aug[sel],aug[col]);longlonginv=modPow(aug[col][col],MOD-2,MOD);// Chuẩn hóa hàng pivot thành 1 ở cột col (để vế trái dần thành I)for(intj=0;j<2*n;j++)aug[col][j]=aug[col][j]*inv%MOD;// Khử cột col ở mọi hàng khác (đưa về 0)for(introw=0;row<n;row++){if(row!=col){longlongfactor=aug[row][col];for(intj=0;j<2*n;j++){aug[row][j]=(aug[row][j]-factor*aug[col][j]%MOD+MOD)%MOD;}}}}// Lấy phần nghịch đảovector<vector<longlong>>inv(n,vector<longlong>(n));for(inti=0;i<n;i++)for(intj=0;j<n;j++)inv[i][j]=aug[i][n+j];returninv;}
intmatrixRank(vector<vector<longlong>>a){intn=a.size(),m=a[0].size();constlonglongMOD=1e9+7;intrank=0;for(intcol=0,row=0;col<m&&row<n;col++){// Tìm pivot != 0 (mod MOD)intsel=-1;for(inti=row;i<n;i++){if((a[i][col]%MOD+MOD)%MOD!=0){sel=i;break;}}if(sel==-1)continue;// cột toàn 0 → không tăng rankswap(a[sel],a[row]);// đưa pivot lên hàng hiện tạilonglonginv=modPow(a[row][col],MOD-2,MOD);// Khử các hàng DƯỚI (trên không cần vì rank chỉ đếm pivot)for(inti=row+1;i<n;i++){longlongfactor=a[i][col]*inv%MOD;for(intj=col;j<m;j++){a[i][j]=(a[i][j]-factor*a[row][j]%MOD+MOD)%MOD;}}rank++;row++;}returnrank;}