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;
    }
    
  • 相关阅读:
    win7下DS、KS、ASIO、WASAPI输出比较
    什么叫时钟漂移(Wander)?时钟漂移与时钟抖动(jitter)的区别
    常见编译/链接错误及其解决办法
    理解 Visual C++ 应用程序的依赖项(msdn)
    初识windows语音采集和回放
    依赖关系、概况关系、关联关系等概念
    VS2010工程转VS2005工程的方法
    speech codec (G.711, G.723, G.726, G.729, iLBC)
    【转】深入剖析iLBC的丢包补偿技术(PLC)
    CSS优先级问题
  • 原文地址:https://www.cnblogs.com/Flash-plus/p/13834223.html
Copyright © 2011-2022 走看看