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 }

   

      

原文地址:https://www.cnblogs.com/greenpepper/p/11711071.html