高斯消元解线性方程组
int a[N][N]
输入矩阵, n n n行, n + 1 n+1 n+1列,下标从0开始
第 n + 1 n+1 n+1列表示方程右边的值(n行即n个方程,n列即n个未知数)
int gauss()
返回矩阵的秩(矛盾无解返回-1),并且系数矩阵化为单位矩阵
int a[N][N]
数组第 n + 1 n+1 n+1列(下标a[i][n]
)是解 x i x_i xi
时间复杂度: O ( n 3 ) O(n^3) O(n3)
//O(n^3)
#include<bits/stdc++.h>
using namespace std;
const int N=110;
const double eps=1e-6;
int n;
double a[N][N];
int gauss()
{
int c,r;
for(c=0,r=0;c<n;c++) //枚举每一列
{
//找该列绝对值最大的一行 精度
int t=r;
for(int i=r;i<n;i++)
if(fabs(a[i][c])>fabs(a[t][c])) t=i;
// 该列都为0 则跳过
if(fabs(a[t][c])<eps) continue;
// 将该行换到第r行
for(int i=c;i<=n;i++) swap(a[r][i],a[t][i]);
// 第r行第一项变成1
for(int i=n;i>=c;i--) a[r][i]/=a[r][c];
// 变成上三角 用第r行去消掉其他所有行的第c列
for(int i=0;i<n;i++)
if(i!=r&&fabs(a[i][c])>eps) //该行第c列不为0
for(int j=n;j>=c;j--)
a[i][j]-=a[i][c]*a[r][j];
r++;
}
if(r<n) //非完美阶梯型
{
for(int i=r;i<n;i++)
if(a[i][n]>eps) return -1; // 等式右端不为0
return r; //返回秩
}
return r;
}
异或方程组
第 n + 1 n+1 n+1列表示方程右边的值(n行即n个方程,n列即n个未知数)
int gauss
返回矩阵的秩
时间复杂度: O ( n 3 ) O(n^3) O(n3)
#include<iostream>
using namespace std;
const int N=110;
int n,a[N][N];
int gauss()
{
int r,c;
for(c=0,r=0;c<n;c++) //枚举列
{
int t=r; //找到不为1的那一行
for(int i=r;i<n;i++)
if(a[i][c]) t=i;
if(!a[t][c]) continue; //该列都是0
// 不为1的一行换到第r行
for(int j=c;j<=n;j++) swap(a[r][j],a[t][j]);
// 异或消 第r行消去他们的第c列
for(int i=0;i<n;i++)
if(i!=r&&a[i][c])
for(int j=n;j>=c;j--)
a[i][j]^=a[r][j];
r++;
}
if(r<n)
{
for(int i=r;i<n;i++)
if(a[i][n]) return -1;
return r;
}
return r;
}
bitset优化异或方程组
bitset的原理大概是将很多数压成一个,从而节省空间和时间,时间复杂度的 w w w通常是32
n n n行 m m m列,即 n n n个方程 m m m个未知数
int gauss
返回矩阵的秩
注意bitset
对于字符串第位在前,而数字第位表示二进制中数字的最低二进制位
时间复杂度: O ( n 3 w ) O(\frac{n^3}{w}) O(wn3)
#include<bitset>
using namespace std;
const int N=1010;
bitset<N> A[N];
int n,m;
int gauss()
{
int r,c;
for(c=0,r=0;c<m;c++)
{
int t=r;
for(int i=r;i<n;i++)
if(A[i][c]) t=i;
if(!A[t][c]) continue;
swap(A[r],A[t]);
for(int i=0;i<n;i++)
if(i!=r&&A[i][c])
A[i]^=A[r];
r++;
}
if(r<m)
{
for(int i=r;i<n;i++)
if(A[i][m]) return -1;
return r;
}
return r;
}