欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

高斯消元④-异或线性方程组,bitset优化-P3164

程序员文章站 2022-07-12 14:11:02
...

题目大意:

给你一个01矩阵大小 n ∗ m n*m nm.让你构造出一组非全零矩阵使得所有点它所相邻的数的1的个数为偶数.
n , m ≤ 40 n,m \leq 40 n,m40

题目思路:

跟POJ1830差不多,列 n ∗ m n*m nm个方程直接跑高斯消元即可.

复杂度: O ( ( n ∗ m ) 3 ) O((n*m)^3) O((nm)3)。可能会超时(实际上不会)。

加上bitset优化即可.复杂度为: O ( ( n ∗ m ) 3 64 ) O(\frac{(n*m)^3}{64}) O(64(nm)3).–其实都不用改什么地方,把数组改成bitset,再把单个异或改成整行异或就好.实际快个400ms左右.

然后就是求具体解:先把*元答案全设为1.跑完高斯消元之后,对每一行选定第一个未知数求解它即可。

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 41;
bitset<maxn * maxn> a[maxn * maxn];
int nx[10] = {0,0,0,-1,1};
int ny[10] = {0,-1,1,0,0};
int res[maxn * maxn] , n , m;
void print ()
{
    cout << endl;
    for (int i = 1 ; i <= n * m ; i++){
        for (int j = 1 ; j <= n * m + 1; j++){
            cout << a[i][j] << " ";
        }
        cout << endl;
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin >> n >> m;
    for (int i = 1 ; i <= n ; i++)
        for (int j = 1 ; j <= m ; j++)
            for (int d = 0 ; d <= 4 ; d++){
                int t = (i - 1) * m + j;
                int gx = i + nx[d] , gy = j + ny[d];
                if (gx <= 0 || gx > n || gy <= 0 || gy > m) continue;
                int tt = (gx - 1) * m + gy;
                a[t][tt] = 1;
            }
    int way = n * m;
    // 高斯消元
    int r , c;
    for (r = c = 1 ; r <= way && c <= way ; r++ , c++){
        int p = 0;
        for (int j = r ; j <= way ; j++){
            if (a[j][c]) {
                p = j;
                break;
            }
        }
        if (!p){
            r--;
            res[c] = 1;
            continue;
        }
        swap(a[p] , a[r]);
        for (int j = 1 ; j <= way ; j++){
            if (j == r) continue;
            if (a[j][c] == 0) continue;
            a[j] ^= a[r];
        }
    }
    // 求一组特定解
    for (int i = 1 ; i <= way ; i++){
        int p = 0;
        // 求解这一行第一个1那个未知数
        for (int j = 1 ; j <= way ; j++){
            if (a[i][j]){
                p = j;
                break;
            }
        }
        if (!p) {
            continue;
        }
        //
        res[p] = a[i][way + 1];
        for (int j = p + 1 ; j <= way ; j++)
            res[p] ^= a[i][j];
    }
    for (int i = 1 ; i <= n ; i++){
        for (int j = 1 ; j <= m ; j++){
            cout << res[(i - 1) * m + j] << " ";
        }
        cout << endl;
    }
    return 0;
}
相关标签: 算法 线性代数