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;
    }
    
  • 相关阅读:
    安卓的sqlite增删改
    C#访问MySQL数据库(winform+EF)
    Sqlite在.NET下的使用和Sqlite数据库清理
    WPF小笔记-Popup拖动
    WPF自定义窗口最大化显示任务栏
    什么是Hash?什么是Hash算法或哈希函数?什么是map?什么是HashMap?HashMap的实现原理或者工作原理?HashMap是线程安全的吗?为什么?如何解决?
    字符串转换整数
    系统顺序图与顺序图区别,以及根据顺序图写代码
    设计领域模型有哪些难点?有哪些指导原则?
    斐波那契数列java实现
  • 原文地址:https://www.cnblogs.com/Flash-plus/p/13834223.html
Copyright © 2011-2022 走看看