高斯消元求解异或方程组

Posted 033000-

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高斯消元求解异或方程组相关的知识,希望对你有一定的参考价值。

POJ1830 开关问题

对于解异或方程组,系数可以采用二进制压缩,如果系数太多可以使用bitset,但是如果少一点就可以使用下述的写法,更加简单快速

使用bitset的写法更正常的没什么区别,只是对应的消除变为异或操作,另外行变换也会更加简单

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int a[100], n, t, ans;
int main() {
    cin >> t;
    while (t--) {
        cin >> n;
        for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
        for (int i = 1, j; i <= n; i++) {
            scanf("%d", &j);
            a[i] ^= j;
            a[i] |= 1 << i; // a[i][i] = 1;-
        }
        int x, y;
        while (~scanf("%d%d", &x, &y) && x && y) {
            a[y] |= 1 << x; // a[y][x] = 1;
        }
        ans = 1;
        for (int i = 1; i <= n; i++) {
            // 找到最大的一个a[i],即主元位数最高的a[i] 
            for (int j = i + 1; j <= n; j++)
                if (a[j] > a[i]) swap(a[i], a[j]);
            // 消元完毕,有i-1个主元,n-i+1个自由元 
            if (a[i] == 0) { ans = 1 << (n - i + 1); break; }
            // 出现0=1的方程,无解
            if (a[i] == 1) { ans = 0; break; }
            // a[i]最高位的1作为主元,消去其他方程该位的系数 
            for (int k = n; k; k--)
                if (a[i] >> k & 1) {
                    for (int j = 1; j <= n; j++)
                        if (i != j && (a[j] >> k & 1)) a[j] ^= a[i];
                    break;
                }
        }
        if (ans == 0) puts("Oh,it‘s impossible~!!");
        else cout << ans << endl; 
    }
}

 

以上是关于高斯消元求解异或方程组的主要内容,如果未能解决你的问题,请参考以下文章

高斯消元法求解异或方程组: cojs.tk 539.//BZOJ 1770 牛棚的灯

poj1830-开关问题高斯消元求解异或方程组

BZOJ.1923.[SDOI2010]外星千足虫(高斯消元 异或方程组 bitset)

高斯消元学习

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

bzoj1923 [Sdoi2010]外星千足虫