• Codeforces 1248 C. Ivan the Fool and the Probability Theory (思维) div2


      题意:给一个n×m的网格,只涂黑白,问再没有三个联通方格的情况下涂色,有多少种涂法?结果mod 1e9+7

      

      直接说解法:

       首先判断第一行的情况,做递推关系式F[ i ],F[ 1 ]显然为2,F[ 2 ]也可以任意,显然为4。

       接下来F[ 3 ],需要分这个的前两个是否为连续相同的色块,如果是连续相同的色块,那么只能与前一个色块不同。我们把F[i]拓展为F[i][j],i表示到第几个块,j表示第i个的前两个是否为连续两块。那么F[ i ]的种类数分为:

        (1):前面是两个连续相同,那么F[ i ]的种数与F[ i - 1 ]的种数相同,且状态变为不连续。即:F[ i ][ 0 ] += F[ i - 1 ] [ 1 ];

          (2)   :前面两个连续不同,那么当前分为两种情况,继续与前面不同,或与前面相同,状态转为连续。既:F[ i ][ 0 ] += F[ i - 1 ][ 0 ], F[ i ][ 1 ] = F[ i - 1 ][ 0 ];

        得出总的递推关系式:

            F[ i ] [ 0 ]  = F[ i - 1 ] [ 0 ] + F[ i -1 ][ 1];

            F[ i ] [ 1 ]  = F[ i - 1 ] [ 0 ];

          F[ 1 ][ 0 ] = 2; F[ 1 ][ 1 ]=0;

       若为i个方块,那么有F[ i ][ 0 ] + F [ i ][ 1 ]种解;

     // 其实涂色方式也可以当作N个台阶,每次上1阶或2阶,问有多少种上阶梯方法。

      两种理解方式都讲递推关系式指向了斐伯纳契。既推出斐伯纳契的第n项与第m项。

      确定第一行后,我们再递推到全部行。

        如果第一行有两个连续的色块,那么下面的每一行都必须与上一行完全相反。如果有相同的,那么必然出现3个连续相同的情况。

          证明: 若上一行连续两个相同处,下一行不完全相反,那么必然有一个和上一个连续相同两处相同,连成3个

             若上一行不连续两个相同处,要有一个与上一行不完全相反

              设上一行为黑白黑白黑

              那么下一行必然有一个黑对黑或白对白,会与左右相同,连成3个相同。

              若完全相同,必然会遇到水平相同两个的与之相连

                  白黑白白黑

                  黑白黑黑白

              会与上面的二连白相同或下面的二连黑相同

           故只有一种下面的结果,每一行与前一行完全相反。

        如果第一行没有两个连续相同的色块,既黑白黑白黑白黑白   或 白黑白黑白黑白黑(共计两种),那么接下来的一行可以与本行完全相等,或者完全相反。并且完全相同只能连续两行。这样的每行递推下来也相当于,没有三行连续相同,即和上面一行中推法一样,所以也是斐伯纳契m项的值。因为初始状态只有两种满足没有两个连续相同色块,所以是2×斐伯纳契m

      那么结果就是 第一行有连续色块,剩下所有行结果已定。 总数为 2×斐伯纳契第n项-2

             第一行无连续色块,剩下种类为斐伯纳契m项,既 2×斐伯纳契第m项

    总结果数量为 2×(斐伯纳契n项+斐伯纳契m项)-2

    以下为AC代码(比赛时没发现行也是斐伯纳契,所以复杂了点。)  

     1 #include<iostream>
     2 using namespace std;
     3 typedef long long ll;
     4 const int mod = 1e9+7;
     5 const int maxn = 1e5+50;
     6 ll dp[maxn][3];
     7 int main(){
     8     int n,m;
     9     cin>>n>>m;
    10     dp[1][0]=2;
    11     dp[1][1]=0;                          //初始化
    12     for(int i=2;i<=n;i++){                //递推
    13         dp[i][0]=dp[i-1][0]+dp[i-1][1];
    14         dp[i][1]=dp[i-1][0];
    15         dp[i][0]%=mod;
    16         dp[i][1]%=mod;
    17     }
    18     ll a,b,c;
    19     a=0,b=1,c=0;
    20     for(int i=0;i<n;i++){    
    21         c=a+b;
    22         a=b;
    23         b=c;
    24         c%=mod;
    25     }
    26     ll res = dp[m][0]+dp[m][1]-2+b*2;    //得结果
    27     res%=mod;
    28     cout<<res<<endl;
    29     return 0;
    30 }

       

          

  • 相关阅读:
    【leetcode】ZigZag——easy
    联合
    AddChildViewController
    imageWithRender(图片的渲染模式)
    13.范型函数的使用:将字典合并到当前字典
    12.代码获取命名空间名称,并创建相应的类(anyClass 应用)
    13.static 面向对象
    11.swift 单例
    swift String 扩展
    swift UIView 扩展
  • 原文地址:https://www.cnblogs.com/greenpepper/p/11711071.html
Copyright © 2020-2023  润新知