zoukankan      html  css  js  c++  java
  • codeforces CF 1574E (combinatorics,组合数学,思维题)

    第一步

    从简化问题入手,我们先考虑所有位置都能自己填的情况,即初始情况:

    尝试以行为单位来从上往下一行一行填数字,很显然当前行的方案数只与上一行的填写情况(即上一行的状态)有关。但是状态太多了,我们找一下规律。

    比如上一行是这么填的:

    10110001

    很显然,如果上一行出现了连续的1,下一行对应位置就必须是连续的0,反过来同理。

    因此下一行目前是这样:

    ??00111?

    再仔细想一下,对四宫格只要确定了三个,第四个就能确定。换句话说,只要该行有一个数字确定,该行就有且只能有一种填写方案。很显然,该方案就是上行的按位取反。

    因此下一行的填写方案是

    01001110

    换句话说,如果第一行的填写方案存在连续的0或1,那么接下来的每一行都能且只能是上一行的取反。设m为列数,则方案数为(2^m-2),减掉的是不存在连续的0或1的方案数一共两种,即010101101010。称为Case1

    对Case1,再换个角度,既然每一行都只能是上一行的反,那么就代表着每一列都是010101或者101010。因此Case1等价于第一行存在连续0或1时,每一列都是01间隔的总填写方案。从这个角度上来看,每列有两种填法,减去第一行不满足情况的填法(这种情况下整个矩阵都是01间隔的,我们把左上角为0的称为01矩阵,左上角为1的称为10矩阵),方案数也是(2^m-2)。下面我们都用这个角度来看待Case1。

    考虑一下余下的情况也就是第一行是01间隔的情况,称为Case2,观察可知第一行有两种填法即010101101010。余下的每一行都可以与上一行相同或者相反。因此方案数是(2^n)

    第二步

    现在考虑矩阵中已有一些位置确定的情况。针对Case2,考虑到每一行只能是010101或者101010的样式,当一行确定了一个数,那么该行就只能有最多一种填法。如果确定了多个数,该行可能就不存在填法。经过第一步的讨论,我们知道Case2中行之间的填法是无关的,因此满足乘法定律,方案数为(2^{空行数})。当然,如果有行不合法,那么方案数为0。

    针对Case1同理,方案数为(2^{空列数})。但是要排除掉的是“能够合法地填成一个矩阵,但是第一行是01间隔”的方案数,而不是简单减2。换句话说,就是如果01矩阵或10矩阵满足当前确定的数字,就要把它们排除掉,因为已经在Case2中被包括进去了。

    第三步

    接下来考虑如何维护状态。

    对每个填入的数字,我们需要考虑这么几件事情:

    对当前行/列能否填成0101的影响;

    对当前行/列能否填成1010的影响;

    对当前能否填成01矩阵的影响;

    对当前能否填成10矩阵的影响。

    对计算结果,我们还需要考虑这么几个全局的计数器:

    当前有几个空行/列;

    当前是否有不合法的行/列。

    分别维护几个计数器或map或set去搞就好了。

    [Ans=(errorRow==0)*2^{emptyRow} + (errorCol==0)*2^{emptyCol} - canMatrix01-canMatrix10 ]

    计数器、map、set都可以退状态,所以删除、添加操作都可以搞。替换操作拆成删除和添加就行了。

    总时间复杂度(O(n))(O(nlog n))

    code:https://codeforces.com/contest/1574/submission/129990500 非常抽象,不建议阅读

  • 相关阅读:
    springcloud概述
    springcloud-微服务架构基础
    TypeScript 教程
    提示工具以及弹出框
    Bootstrap 弹出框(Popover)插件
    JavaScript JSON
    JavaScript常见基础函数
    7种JavaScript代码调试的方法
    Bootstrap 网格系统
    文本元素
  • 原文地址:https://www.cnblogs.com/zhugezy/p/15347123.html
Copyright © 2011-2022 走看看