Ivan the Fool and the Probability Theory-Codeforces Round #594 (Div. 2)-C题(dp+思维)

Ivan the Fool and the Probability Theory-Codeforces Round #594 (Div. 2)-C题(dp+思维)

time limit per test:1 second
memory limit per test:512 megabytes
input:standard input
output:standard output

描述

Recently Ivan the Fool decided to become smarter and study the probability theory. He thinks that he understands the subject fairly well, and so he began to behave like he already got PhD in that area.

To prove his skills, Ivan decided to demonstrate his friends a concept of random picture. A picture is a field of n n rows and m m columns, where each cell is either black or white. Ivan calls the picture random if for every cell it has at most one adjacent cell of the same color. Two cells are considered adjacent if they share a side.

Ivan’s brothers spent some time trying to explain that it’s not how the randomness usually works. Trying to convince Ivan, they want to count the number of different random (according to Ivan) pictures. Two pictures are considered different if at least one cell on those two picture is colored differently. Since the number of such pictures may be quite large, print it modulo 1 0 9 + 7 10^9+7 .

Input

The only line contains two integers n n and m ( 1 n , m 100000 ) m (1≤n,m≤100000) , the number of rows and the number of columns of the field.

Output

Print one integer, the number of random pictures modulo 1 0 9 + 7 10^9+7 .

Example

input

2 3

output

8

Note

The picture below shows all possible random pictures of size 2 by 3.

在这里插入图片描述

题解

题读到一半,联想起状压 d p dp ,但是一看到 100   000 100\ 000 果断放弃。╮(╯▽╰)╭

然后想起普通 d p dp ,再一看 n n m m 都是 100   000 100\ 000 果断放弃。╮(╯▽╰)╭

数一下0,嗯,有 5 5 个,说明 O ( n   l o g   n ) O(n\ log\ n) 能过,可是又想不到什么用得上的算法,最后决定还是得用 d p dp 做。

仔细一想不难发现,当第一行存在两个相同的颜色连在一起的情况时剩下所有的方块只有一种排列方式,也就是说只要第一排确定了且第一排存在两个相同的连在一起的方块,这种情况就只有一种排列方式。形如这样:
在这里插入图片描述
当宽度为 m m 时,定义 d p [ i ] dp[i] 是宽度为 i + 1 i+1 的(从0开始数)方格的方法数。
那么 d p [ 0 ] = 2 , d p [ 1 ] = 4 dp[0]=2,dp[1]=4

d p [ i ] = d p [ i 2 ] + d p [ i 1 ] dp[i]=dp[i-2]+dp[i-1]

证明如下:


d p [ i ] [ 2 ] dp[i][2]

d p [ i ] [ 0 ] dp[i][0] 表示宽度为 i + 1 i+1 (从0开始数)且下标为i的位置放置白方块的方格的方法数。
那么相应的 d p [ i ] [ 1 ] dp[i][1] 表示宽度为 i + 1 i+1 (从0开始数)且下标为i的位置放置黑方块的方格的方法数。

所以有 d p [ 0 ] [ 0 ] = 1 dp[0][0]=1 (只有一个格而且只能放白方块,所以只有一种情况);
d p [ 0 ] [ 1 ] = 1 dp[0][1]=1 (只有一个格而且只能放黑方块,所以只有一种情况);
d p [ 1 ] [ 0 ] = 2 dp[1][0]=2 (不论第一个位置是什么颜色,这里都能放白色,故有两种情况)
d p [ 1 ] [ 1 ] = 2 dp[1][1]=2 (不论第一个位置是什么颜色,这里都能放黑色,故有两种情况)

在这里插入图片描述
由图可知: d p [ i ] [ 1 ] = d p [ i 2 ] [ 0 ] + d p [ i 1 ] [ 0 ] dp[i][1]=dp[i-2][0]+dp[i-1][0]

在这里插入图片描述
由图可知: d p [ i ] [ 0 ] = d p [ i 2 ] [ 1 ] + d p [ i 1 ] [ 1 ] dp[i][0]=dp[i-2][1]+dp[i-1][1]

把两式相加会发现 d p [ i ] [ 0 ] + d p [ i ] [ 1 ] = d p [ i 1 ] [ 0 ] + d p [ i 1 ] [ 1 ] + d p [ i 2 ] [ 0 ] + d p [ i 2 ] [ 1 ] dp[i][0]+dp[i][1]=dp[i-1][0]+dp[i-1][1]+dp[i-2][0]+dp[i-2][1]

d p [ i ] [ 0 ] + d p [ i ] [ 1 ] dp[i][0]+dp[i][1] 看成一个整体,方程可以写成 d p [ i ] = d p [ i 2 ] + d p [ i 1 ] dp[i]=dp[i-2]+dp[i-1]

即长度为 i + 1 i+1 的一行格子有 d p [ i ] dp[i] 种排列方法,宽度为 m m 的第一行就有 d p [ m 1 ] dp[m-1] 种排列方法
而一定包含至少一对相同的块相连的情况是 d p [ m 1 ] 2 dp[m - 1]-2 (除去黑白交替的两种情况)

证毕


而剩下的就是第一排所有相同的的方块都不连的情况了。如图:
在这里插入图片描述
这个时候会发现, n n 行方块一共只有两行不一样的状态(先放黑块和先放白块,然后交替出现),把其中一行看作一个白方块,把另一行看作黑方块,问题就变成了 n n 行里排列黑白方块,且最多只有一对颜色相同的块互相连接。那么答案显然就是 d p [ n 1 ] dp[n-1] (证明如上)。

即答案就是 d p [ m 1 ] + d p [ n 1 ] 2 dp[m-1]+dp[n-1]-2

代码

#include <iostream>
#include <algorithm>
#include <vector>
#define maxn 100005
#define _for(i, a) for(LL i = 0; i < (a); i++)
#define _rep(i, a, b) for(LL i = (a); i <= (b); i++)
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;

LL dp[maxn];	//0:do	1:not do

int main() {
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	//freopen("in.txt", "r", stdin);

	int n, m;
	cin >> n >> m;
	dp[0] = 2, dp[1] = 4;
	if (n < m) swap(n, m);
	_rep(i, 2, n - 1) {
		dp[i] = dp[i - 2] + dp[i - 1];
		dp[i] %= mod;
	}
	cout << (dp[n - 1] - 2 + dp[m - 1]) % mod << "\n";
	return 0;
}

发布了163 篇原创文章 · 获赞 54 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/weixin_42856843/article/details/102655689