Codeforces Round #594 (Div. 2) - C. Ivan the Fool and the Probability Theory(思维)
题意:给n*m的网格涂黑白两种颜色,保证每个格子上下左右的四个格子中最多只有一个格子与自己颜色相同,问有多少种涂法?结果$mod1000000007$
思路:先只考虑一行有多少种涂法
- $dp[i][0]$表示第$i$个格子与第$i-1$个格子颜色不一样,那么第$i-1$与第$i-2$个格子颜色可以不同也可以相同,所以$dp[i][0]=dp[i-1][1]+dp[i-1][0]$
- $dp[i][1]$表示第$i$个格子与第$i-1$个格子颜色相同,那么第$i-1$与第$i-2$格子颜色只能不相同,所以$dp[i][1]=dp[i-1][0]$
再考虑其他行的情况:
- 第一行有两个连续格子颜色相同时的情况(即 黑黑白黑白...这种情况),这时第二行必须跟第一行完全相反才能符合题意。
证明如下:以 黑黑白黑白 为例,如果 黑黑 的下一行出现了 黑,显然不符合题意,所以 黑黑 的下一行只能为 白白,其次如果第三个 白 的下一行为 白,就和前面的两个 白 组成了连续的三个 白,不符合题意,所以此时下一行必须与上一行完全相反。
- 第一行没有两个连续格子颜色相同时的情况(即 黑白黑白黑白...这种情况),设$f(i)$表示加入第$i$行时有多少种情况,如果第$i-1$和第$i-2$行颜色相同,那么第$i$行与第$i-1$行颜色不能相同,如果第$i-1$和第$i-2$行颜色不同,那么第$i$行和第$i-1$行颜色可以相同也可以不同,先假设第$i$行与第$i-1$行颜色不同,那么有$f(i-1)$种,只有当第$i-1$行与第$i-2$行颜色不同时第$i$行与第$i-1$行颜色才能相同,有$f(i-2)$种,所以$f(i)=f(i-1)+f(i-2)$,满足斐波那契数列。
第一种情况有$dp[m][0]+dp[m][1]-2$种(除去 黑白黑白黑白... 白黑白黑白黑... 这两种情况),第二种情况只有两种,所以最后的方案数为$dp[m][0]+dp[m][1]-2+2*f(n)$
其实行和列都是斐波那契数列,比赛时没看出来,答案为$2*(f(n)+f(m))-2$
#include <iostream> #include <cstdio> #include <algorithm> using namespace std; typedef long long ll; const int N = 100010; const ll mod = int(1e9) + 7; ll dp[N][2], n, m; ll f[N]; int main() { scanf("%lld%lld", &n, &m); dp[1][0] = 2, dp[1][1] = 0; for (int i = 2; i <= m; i++) { dp[i][0] = (dp[i - 1][1] + dp[i - 1][0]) % mod; dp[i][1] = dp[i - 1][0] % mod; } f[1] = 1, f[2] = 2; for (int i = 3; i <= n; i++) f[i] = (f[i - 1] + f[i - 2]) % mod; ll res = (dp[m][1] + dp[m][0]) % mod; ll ans = ((f[n] * 2) % mod + (res - 2) % mod) % mod; printf("%lld\n", ans); return 0; }