高斯消元 解线性方程组 解异或线性方程组

目录

  • 高斯消元解线性方程组
    • 代码实现
  • 高斯消元解异或线性方程组
    • 核心思想
    • 代码实现


高斯消元解线性方程组

题目描述:
输入一个包含 n n n 个方程 n n n 个未知数的线性方程组。

方程组中的系数为实数。

求解这个方程组。

下图为一个包含 m m m 个方程 n n n 个未知数的线性方程组示例:

{ a 11 x 1 + a 12 x 2 + ⋯ + a 1 n x n = b 1 a 21 x 1 + a 22 x 2 + ⋯ + a 2 n x n = b 2 ⋮ a m 1 x 1 + a m 2 x 2 + ⋯ + a m n x n = b m \begin{cases} a_{11}x_1 + a_{12}x_2 + \cdots + a_{1n}x_n = b_1 \\ a_{21}x_1 + a_{22}x_2 + \cdots + a_{2n}x_n = b_2 \\ \vdots \\ a_{m1}x_1 + a_{m2}x_2 + \cdots + a_{mn}x_n = b_m \end{cases} a11x1+a12x2++a1nxn=b1a21x1+a22x2++a2nxn=b2am1x1+am2x2++amnxn=bm

输入格式:
第一行包含整数 n n n

接下来 n n n 行,每行包含 n + 1 n+1 n+1 个实数,表示一个方程的 n n n 个系数以及等号右侧的常数。

输出格式:
如果给定线性方程组存在唯一解,则输出共 n n n 行,其中第 i i i 行输出第 i i i 个未知数的解,结果保留两位小数。

如果给定线性方程组存在无数解,则输出 Infinite group solutions

如果给定线性方程组无解,则输出 No solution

数据范围:
1 ≤ n ≤ 100 1≤n≤100 1n100,所有输入系数以及常数均保留两位小数,绝对值均不超过 100。

输入样例:

3
1.00 2.00 -1.00 -6.00
2.00 1.00 -3.00 -9.00
-1.00 -1.00 2.00 7.00

输出样例:

1.00
-2.00
3.00

代码实现

#define _CRT_SECURE_NO_WARNINGS
#include
using namespace std;

const int N = 110;
const double eps = 1e-8;
double a[N][N];
int n;

int gauss()
{
	int row = 0;
	for (int col = 0; col < n; col++)
	{
		int t = row;
		for (int i = row + 1; i < n; ++i) // 在当前列找绝对值最大的行
			if (fabs(a[t][col]) - fabs(a[i][col]) < eps) t = i;

		if (fabs(a[t][col]) < eps) continue; // 当前列所有元素都为0,则直接进入下轮循环
		for (int i = n; i >= col; --i)
		{
			a[t][i] /= a[t][col]; // 将绝对值最大的行首位化简为1
			swap(a[t][i], a[row][i]); // 将此行换到最顶端
		}
		for (int i = row + 1; i < n; ++i) // 用当前行将下面所有的行的对应列位置的元素消成0
		{
			if (fabs(a[i][col]) < eps) continue;
			for (int j = n; j >= col; --j) a[i][j] -= a[i][col] * a[row][j];
		}
		row++;
	}

	// 判断解唯一性
	if (row < n) // 系数矩阵的秩 < n
	{
		// 判断系数矩阵的秩与增广矩阵是否相同
		for (int i = row; i < n; ++i)
			if (fabs(a[i][n]) > eps) return 0; 
		return 2;
	}
	for (int i = n - 1; i >= 0; --i)
	{
		for (int j = i + 1; j < n; ++j)
			a[i][n] -= a[i][j] * a[j][n]; // 这一步巧妙
	}
	return 1;
}
int main()
{
	cin >> n;
	for (int i = 0; i < n; ++i)
	{
		for (int j = 0; j <= n; ++j)
			cin >> a[i][j];
	}
	int flag = gauss();
	if (flag == 0)
		cout << "No solution" << endl;
	else if (flag == 1)
		for (int i = 0; i < n; ++i) cout << a[i][n] << endl;
	else
		cout << "Infinite group solutions" << endl;
	return 0;
}

高斯消元解异或线性方程组

异或运算又称为不进位的加法

题目描述:

输入一个包含 n n n 个方程 n n n 个未知数的异或线性方程组。

方程组中的系数和常数为 0 0 0 1 1 1,每个未知数的取值也为 0 0 0 1 1 1

求解这个方程组。

异或线性方程组示例如下:

M[1][1]x[1] ^ M[1][2]x[2] ^^ M[1][n]x[n] = B[1]
M[2][1]x[1] ^ M[2][2]x[2] ^^ M[2][n]x[n] = B[2]
…
M[n][1]x[1] ^ M[n][2]x[2] ^^ M[n][n]x[n] = B[n]

其中 ^ 表示 异或(XOR) M [ i ] [ j ] M[i][j] M[i][j] 表示第 i i i 个式子中 x [ j ] x[j] x[j] 的系数, B [ i ] B[i] B[i] 是第 i i i 个方程右端的常数,取值均为 0 0 0 1 1 1

输入格式:
第一行包含整数 n n n

接下来 n n n 行,每行包含 n + 1 n+1 n+1 个整数 0 0 0 1 1 1,表示一个方程的 n n n 个系数以及等号右侧的常数。

输出格式:
如果给定线性方程组存在唯一解,则输出共 n n n 行,其中第 i i i 行输出第 i i i 个未知数的解。

如果给定线性方程组存在多组解,则输出 Multiple sets of solutions

如果给定线性方程组无解,则输出 No solution

数据范围:
1 ≤ n ≤ 100 1≤n≤100 1n100

输入样例:

3
1 1 0 1
0 1 1 0
1 0 0 1

输出样例:

1
0
0

核心思想

异或-不进位的加法

等式与等式间的异或要一起进行才能保证等式左右两边依然是相等关系。

a a a ^ b b b ^ c c c = x x x
d d d ^ f f f = y y y

a a a ^ b b b ^ d d d ^ c c c ^ f f f = x x x ^ y y y

位运算中的^既可以对应加法,也可以对应减法,&可以对应乘法。


代码实现

#define _CRT_SECURE_NO_WARNINGS
#include
using namespace std;

const int N = 110;
int a[N][N];
int n;

int gauss()
{
	int row = 0;
	for (int col = 0; col < n; ++col)
	{
		int t = row;
		for (int i = row; i < n; ++i)
			if (a[i][col])
			{
				t = i;
				break;
			}
		if (!a[t][col]) continue;
		for (int i = col; i <= n; ++i) swap(a[t][i], a[row][i]);
		for (int i = row + 1; i < n; ++i)
		{
			if (!a[i][col]) continue;
			for (int j = n; j >= col; --j)
				a[i][j] ^= a[i][col] & a[row][j]; // 写成a[i][j] ^= a[i][col] * a[row][j];也可
		}
		row++;
	}
	if (row < n)
	{
		for (int i = row; i < n; ++i)
			if (a[i][n]) return 0;
		return 2;
	}
	for (int i = n - 1; i >= 0; --i)
	{
		for (int j = i + 1; j < n; ++j)
			a[i][n] ^= a[i][j] & a[j][n];
	}
	return 1;
}
int main()
{
	cin >> n;
	for (int i = 0; i < n; ++i)
		for (int j = 0; j <= n; ++j) cin >> a[i][j];
	int t = gauss();
	if (t == 0) cout << "No solution" << endl;
	else if (t == 1)
		for (int i = 0; i < n; ++i) cout << a[i][n] << endl;
	else cout << "Multiple sets of solutions" << endl;
	return 0;
}

你可能感兴趣的:(从零开始的算法打灰,算法,c++)