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

  题意:给一个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

时间: 2024-10-25 15:09:41

Codeforces 1248 div2 C. Ivan the Fool and the Probability Theory (思维)的相关文章

Codeforces Round #594 (Div. 2) C. Ivan the Fool and the Probability Theory

题目原址:C. Ivan the Fool and the Probability Theory 题意:n×m的网格中填黑白格,最多有两个相邻,共用一条边为相邻,有几种填法. 思路:这题比赛写自闭了,一直觉得自己的思路没错,然后就残酷打脸,超级难受的那种. 从不能有3个及以上相邻可以得出,只要有两个相邻的就能确定全部的分布,那就变成了求一行的方法数量,再减去黑白相间的两种,而剩下就是黑白相间两种情况时有多少种了. 一行的求法:dp[ i ] [ 0 ]表示在第 i 个格子里放白色的放法有多少,d

Codeforces Round #594 (Div. 2) B C - Ivan the Fool and the Probability Theory

题目链接:https://codeforces.com/contest/1248/problem/C 赛后补的,已经有很详细的题解了,这里只作一个记录. 每相邻两行只可能完全相同或者完全不同,而每一行只有1010101010……和01010101010……是没有连续相邻的(有连续相邻的下一行只能完全不同,即有连续相邻的从第一行开始后面的就已经固定了),n=1时答案是递推数列,F[n] = F[n-1] + F[n-2].当第一行为10101010……或0101010101时每一行只有两种状态,此

[CF1239A] Ivan the Fool and the Probability Theory - 组合数学

给定一个 \(n \times m\) 的方格图,每个格子可以被染成黑色或白色,且与其相邻的格子(上,下,左,右)中至多只有一个与其颜色相同.求方案数. Solution 依稀记得当年在热身赛上碰到这个题,大家都说是 CF 原题,然后我跪了-- 对于 \((i,j)\),如果它左.左上.上的颜色确定,那么这个格子的颜色就确定了 于是我们枚举 \((1,1)\) 的颜色,然后将第一行第一列的颜色确定下来,这时候行列显然相互独立 对于行,答案相当于一个 \(1/2\) 排列划分,对于列同理,于是答案

Codeforces 583 DIV2 Robot&#39;s Task 贪心

原题链接:http://codeforces.com/problemset/problem/583/B 题意: 就..要打开一个电脑,必须至少先打开其他若干电脑,每次转向有个花费,让你设计一个序列,使得总花费最小. 题解: 就傻傻的走就好..从左走到右,再走回来,更新序列和答案就好. 代码: #include<iostream> #include<cstring> #include<algorithm> #include<cstdio> #define MA

Codeforces #180 div2 C Parity Game

// Codeforces #180 div2 C Parity Game // // 这道题的题目意思就不解释了 // // 题目有那么一点难(对于我而言),不多说啦 // // 解题思路: // // 首先如果a串和b串相等,不多说直接YES // 如果b串全是0,直接YES // 注意到a串有一个性质,1的个数不会超过本身的加1. // a有个1的上限设为x,b有个1的个数设为y,则如果x < y // 那么直接NO. // // 现在一般情况下,就是模拟啦,找到a的后缀和b的前缀一样的

Codeforces #246(div2)

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <ti

Codeforces #245(div2)

A:A. Points and Segments (easy) 题目看了n久,开始觉得尼玛这是div2的题目么,题目还标明了easy.. 意思是给你一n个点,m个区间,在n个点上放蓝球或者红球,然后让你找一种选择方案使得m个区间内的蓝球和红球数量之差不超过1. 开始想过用dfs,不过这只是div2的A题而已.. 然后想了下,直接输出010101序列不就可以么. 交了一发,发现要先排个序,再输出就可以了. AC代码: #include<iostream> #include<cstdio&g

codeforces#327 div2

codeforces#327 div2 这场状态不好有点可惜,题目都不难,而且很好.. A题:水题. #include<bits/stdc++.h> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; typedef lo

codeforces#FF(div2) DZY Loves Sequences

n个数,可以任意改变其中一个数,求最长的上升子区间长度 思路:记录一个from[i]表示从位置i的数开始最长的上升区间长度 记录一个to[i]表示到位置i的数所能达到的最长上升区间长度 枚举要改变的数的位置i,此时能达到的长度为to[i - 1] + from[i + 1] + 1,取最大值 //#pragma comment(linker, "/STACK:102400000,102400000") //HEAD #include <cstdio> #include &l