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

题目描述:

输入一个包含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;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值