zoukankan      html  css  js  c++  java
  • 题解 CF1391D

    比较哥哥。。。

    题意:

    给一个 (n imes m)(01) 矩阵,定义一个矩阵是好的当且仅当他每一个边长为偶数的子正方形矩阵都恰有奇数个 (1) ,问至少需要修改几个位置才能是的这个矩阵是好的(不可能输出-1)

    数据范围 :

    (n imes m geq 10^6)

    题解:

    首先,对于 (n geq 4) && (m geq 4) 的是肯定无解的

    证明如下:

    如果 (n geq 4) && (m geq 4)

    那么肯定存在 (4 imes 4) 的矩阵。

    那么这个 (4 imes 4) 应该要有奇数个 (1)

    但这个 (4 imes 4) 可以被分成 (4)(2 imes 2)

    每个 (2 imes 2) 要有奇数个 (1)

    (4) 个加起来就是偶数了。

    矛盾。

    再考虑其他情况。

    直接暴力 (dp) 一下就行了。

    因为必然有一个数小于 (3)

    所以复杂度最劣是 (O(10^6 / 3 * 8^2) = O(2e8 + 1e7))

    信仰一波就过了。。。

    至于如何 (dp) 还需要分类讨论。

    (n(m) == 1)(puts("0");) 就行了。

    (n(m) == 2)

    枚举 (0 o 3) 的所有情况。

    (dp[i][k] = min(dp[i][k], dp[i-1][j]) ^ (a[i]))

    (n(m) == 3)

    枚举 (0 o 7) 的所有情况。

    (dp[i][k] = min(dp[i][k], dp[i-1][j]) ^ (a[i]))

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #include <cmath>
    #define maxn 1000010
    #define maxm 1000010
    #define ls x << 1
    #define rs x << 1 | 1
    #define inf 2000000000
    #define inc(i) (++ (i))
    #define dec(i) (-- (i))
    #define mid ((l + r) >> 1)
    #define int long long
    #define XRZ 1000000000
    #define debug() puts("XRZ TXDY");
    #define mem(i, x) memset(i, x, sizeof(i));
    #define Next(i, u) for(register int i = head[u]; i ; i = e[i].nxt)
    #define file(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout);
    #define Rep(i, a, b) for(register int i = (a) , i##Limit = (b) ; i <= i##Limit ; inc(i))
    #define Dep(i, a, b) for(register int i = (a) , i##Limit = (b) ; i >= i##Limit ; dec(i))
    int dx[10] = {1, -1, 0, 0};
    int dy[10] = {0, 0, 1, -1};
    using namespace std;
    inline int read() {
        register int x = 0, f = 1; register char c = getchar();
        while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
        while(c >= '0' && c <= '9') x = x * 10 + c - 48, c = getchar();
        return x * f;
    } int a[maxn], f[maxn][8], b[8]; char s;
    signed main() { int n = read(), m = read();
    	if(n >= 4 && m >= 4) { puts("-1"); goto QwQ;}
    	if(n >= m) Rep(i, 1, n) Rep(j, 1, m) scanf(" %c", &s), a[i] = (a[i] << 1) + s - '0';
    	else { Rep(i, 1, n) Rep(j, 1, m) scanf(" %c", &s), a[j] = (a[j] << 1) + s - '0'; swap(n, m);}
    	if(m == 1) { puts("0"); goto QwQ;} Rep(i, 1, 7) b[i] = b[i - (i & -i)] + 1;
    	if(m == 2) { Rep(i, 1, n) Rep(j, 0, 3) f[i][j] = inf; Rep(i, 0, 3) f[1][i] = b[i ^ a[1]]; int Ans = inf;
    		Rep(i, 2, n) Rep(j, 0, 3) Rep(k, 0, 3) if(b[j] + b[k] & 1) f[i][k] = min(f[i][k], f[i - 1][j] + b[k ^ a[i]]);
    		Rep(i, 0, 3) Ans = min(Ans, f[n][i]); if(Ans > XRZ) puts("-1"); else printf("%lld", Ans);
    	} else { Rep(i, 1, n) Rep(j, 0, 7) f[i][j] = inf; Rep(i, 0, 7) f[1][i] = b[i ^ a[1]]; int Ans = inf;
    		Rep(i, 2, n) Rep(j, 0, 7) Rep(k, 0, 7) if((b[j & 3] + b[k & 3] & 1) && (b[j >> 1] + b[k >> 1] & 1)) f[i][k] = min(f[i][k], f[i - 1][j] + b[k ^ a[i]]);
    		Rep(i, 0, 7) Ans = min(Ans, f[n][i]); if(Ans > XRZ) puts("-1"); else printf("%lld", Ans);
    	} QwQ:; return 0;
    }
    
  • 相关阅读:
    运算符
    数据类型
    试题汇总
    文件读写
    Python操作
    字符串常用函数 void
    向量叉乘求任意多边形面积,凹凸均可 void
    约瑟夫问题各种求解办法 void
    大数类相关计算(c语言版) void
    求解一元多次方程(迭代法) void
  • 原文地址:https://www.cnblogs.com/Flash-plus/p/13834223.html
Copyright © 2011-2022 走看看