题目描述:
输入一个包含n个方程n个未知数的异或线性方程组。方程组中的系数和常数为0或1,每个未知数的取值也为0或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]表示第i个式子中x[j]的系数,B[i]是第i个方程右端的常数,取值均为0或1。
输入格式
第一行包含整数n。接下来n行,每行包含n+1个整数0或1,表示一个方程的n个系数以及等号右侧的常数。
输出格式
如果给定线性方程组存在唯一解,则输出共n行,其中第i行输出第i个未知数的解。
如果给定线性方程组存在多组解,则输出“Multiple sets of solutions”。
如果给定线性方程组无解,则输出“No solution”。
数据范围
1≤n≤100
输入样例:
3
1 1 0 1
0 1 1 0
1 0 0 1
输出样例:
1
0
0
分析:
与一般的高斯消元求解线性方程组相比,本题更为简单,因为一方面异或方程组的系数只有1或者0,化为行阶梯型更为简单。另一方面矩阵在进行初等变换时只用考虑两种操作,其一是交换两行,其二是将两行异或。故本题的思路是先找到当前列中为1的任意一行,与最上面的行交换,之后考察下面各行,如果当前列的值是1,则异或上最上面行的值,否则继续考察下一行。当矩阵化为行阶梯型之后,也只需自下而上慢慢的异或上下面的行,从而求出方程组的解。具体有无解,有解是唯一解还是无穷多解的判断与高斯消元解线性方程组的判断完全一样。
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 105;
int n,a[maxn][maxn];
int gauss(){
int r,c;
for(r = c = 0;c < n;c++){
int t = r;
for(int i = r;i < n;i++){
if(a[i][c]){
t = i;
break;
}
}
if(!a[t][c]) continue;
for(int i = c;i <= n;i++) swap(a[t][i],a[r][i]);
for(int i = r + 1;i < n;i++){
if(a[i][c]){
for(int j = c;j <= n;j++) a[i][j] ^= a[r][j];
}
}
r++;
}
if(r < n){
for(int i = r;i < n;i++){
if(a[i][n]) return 2;
}
return 1;
}
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 0;
}
int main(){
cin>>n;
for(int i = 0;i < n;i++)
for(int j = 0;j <= n;j++) cin>>a[i][j];
int res = gauss();
if(res == 0){
for(int i = 0;i < n;i++) cout<<a[i][n]<<endl;
}
else if(res == 1) puts("Multiple sets of solutions");
else puts("No solution");
return 0;
}