3503: [Cqoi2014]和谐矩阵

3503: [Cqoi2014]和谐矩阵

链接

分析:

  对于每个点,可以列出一个方程a[i][j]=a[i][j-1]^a[i][j+1]^a[i-1][j]^a[i+1][j],于是可以列出n*m个方程,高斯消元,复杂度$O(n^3m^3)$。可以再bitset优化一下。

  还有一种复杂度更优的做法:如果知道了第一行,那么整个矩阵都可以推出来了,即每个点可以有第一行的几个位置异或得到。

  所以可以推出每一行每个点,与第一行的那些点有关系,推得时候转化以下上面的式子,使得每一个点只与上面的行有关系。

  由于第n+1行只能全部是0,所以可以推出第n+1行每个点与第一行每个点的关系,然后列出m个方程,高斯消元,复杂度$O(m^3)$。

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<cctype>
#include<set>
#include<queue>
#include<vector>
#include<map>
using namespace std;
typedef long long LL;

inline int read() {
    int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
    for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
}

const int N = 55;
LL a[N][N], b[N][N], c[N][N];
int n, m;

void Gauss() {
    for (int k = 1; k <= m; ++k) {
        int r = k;
        while (r <= m && !a[r][k]) r ++;
        if (r > m) continue;
        if (r != k) for (int j = 1; j <= m; ++j) swap(a[k][j], a[r][j]);
        for (int i = k + 1; i <= m; ++i) 
            if (a[i][k]) for (int j = 1; j <= m; ++j) a[i][j] ^= a[k][j];
    }
    for (int i = m; i; --i) {
        if (!a[i][i]) { c[1][i] = 1; continue; }
        c[1][i] = a[i][m + 1];
        for (int j = i + 1; j <= m; ++j) if (a[i][j]) c[1][i] ^= c[1][j]; 
    }
}
int main() {
    n = read(), m = read();
    for (int i = 1; i <= m; ++i) b[1][i] = (1ll << (i - 1));
    for (int i = 2; i <= n + 1; ++i)
        for (int j = 1; j <= m; ++j) 
            b[i][j] = b[i - 1][j - 1] ^ b[i - 1][j] ^ b[i - 1][j + 1] ^ b[i - 2][j];
    for (int i = 1; i <= m; ++i) 
        for (int j = 1; j <= m; ++j) a[i][j] = (b[n + 1][i] >> (j - 1)) & 1;
    Gauss();
    for (int i = 2; i <= n; ++i)
        for (int j = 1; j <= m; ++j) 
            c[i][j] = c[i - 1][j - 1] ^ c[i - 1][j] ^ c[i - 1][j + 1] ^ c[i - 2][j];
    for (int i = 1; i <= n; ++i, puts("")) 
        for (int j = 1; j <= m; ++j) printf("%lld ", c[i][j]);
    return 0;
}

 

posted @ 2019-03-03 21:03  MJT12044  阅读(219)  评论(0编辑  收藏  举报