• 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;
    }
  • 相关阅读:
    Spring和Mybatis整合
    Spring的基本操作
    mybatis在xml文件中处理特殊符号(如:大于号小于号等的方法)
    配置MyBatis 环境
    iframe元素內嵌页面如何去掉继承的html及body背景色/背景图片
    如何解决include包含页面的乱码问题
    Servlet重定向后,页面混乱的解决办法
    使用Ajax验证邮箱是否存在
    使用监听器监听用户访问页面的次数
    基于arduino的红外传感系统
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10467579.html
Copyright © 2020-2023  润新知