题目原址:C. Ivan the Fool and the Probability Theory
题意:n×m的网格中填黑白格,最多有两个相邻,共用一条边为相邻,有几种填法。
思路:这题比赛写自闭了,一直觉得自己的思路没错,然后就残酷打脸,超级难受的那种。
从不能有3个及以上相邻可以得出,只要有两个相邻的就能确定全部的分布,那就变成了求一行的方法数量,再减去黑白相间的两种,而剩下就是黑白相间两种情况时有多少种了。
一行的求法:dp[ i ] [ 0 ]表示在第 i 个格子里放白色的放法有多少,dp[ i ] [ 1 ] 表示在第 i 个格子里放黑色的放法有多少,显然dp [ 1 ] [ 0 ] = 1;dp [ 1 ] [ 1 ] = 1 ; dp [ 2 ] [ 0 ] = 2 ; dp [ 2 ] [ 1 ] = 2 ; 而接着就可以得到dp[ i ] [ 0 ] = dp [ i - 1 ] [ 1 ] + dp [ i - 2 ] [ 1 ] ; 第 i 个放白色那它前一个可以是放黑色,也可以前前个是放黑色,但不能前前前个,因为最多两个。后面的就是一样的。而黑色的推导是一样的,就能得到dp [ i ] = dp[ i - 1 ] + dp [ i - 2 ]。dp[ i ]表示有i个格子有几种放法。
接下来就会发现,列只有两种情况(先放黑块或先放白块,接着交替出现),可以把其中每一行都看成而第一个是相同颜色。就成了在一列n个格子里放黑白块,最多两个一样颜色相邻。
最后结果就是 dp [ n ] + dp [ m ] - 2 了。
AC代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 typedef long long ll; 7 ll x,y; 8 ll dp[100010]; 9 const ll MOD=1e9+7; 10 void ress(){ 11 dp[1]=2; 12 dp[2]=4; 13 for(ll i=3;i<100010;i++) 14 dp[i]=(dp[i-1]+dp[i-2])%MOD; 15 } 16 void sol(){ 17 ress(); 18 ll ans=(dp[x] + dp[y]-2)%MOD; 19 cout<<ans; 20 } 21 int main(){ 22 cin>>x>>y; 23 sol(); 24 return 0; 25 }