返回顶部

Codeforces Round #594 (Div. 2) C. Ivan the Fool and the Probability Theory (思维,递推)

  • 题意:给你一个\(n\)x\(m\)的矩阵,需要在这些矩阵中涂色,每个格子可以涂成黑色或者白色,一个格子四周最多只能有\(2\)个和它颜色相同的,问最多有多少种涂色方案.

  • 题解:首先我们考虑一维的情况,一个格子的方案数是\(2\),两个格子的方案数是\(4\),我们记\(f[1]=2\),\(f[2]=4\),然后我们考虑三个格子的情况,假如我们最后两个格子涂成一样的颜色,那么情况数就是\(f[1]\),若最后两个两个格子的颜色不一样,那么我们可以看成在\(f[2]\)的基础上涂第三个格子,这样涂的话是固定的,即方案数为\(f[2]\),所以可以推出\(f[3]=f[1]+f[2]\),进而求出递推式:\(f[i]=f[i-1]+f[i-2]\).

    我们可以先看第一行的情况,不难发现,假如这一行出现两个连续的颜色时,整个图就确定了,而且这种情况下的第一列一定是黑白相间的,假如没有出现两个连续的颜色,即\(oxoxoxox\)\(xoxoxoxo\)这两个特殊情况,我们是不能确定下面行的情况的,这时我们就可以将这两个情况单独拿出来,去看第一列的情况,在计算这一列的时候,我们必须要保持第一行是\(oxoxoxoxo\)\(xoxoxoxoxo\),就像之前说的,假如出现两个连续的颜色时,第一行的颜色一定是黑白相间的,但是当第一列出现\(oxoxoxox\)\(xoxoxoxo\)这样的情况时,第一行并不一定是黑白相间的,而不是黑白相间的情况我们在\(f[n]\)中已经计算过了,所以方案数为\(f[m]-2\),所以答案就是\(f[n]+f[m]-2\).

  • 代码:

#include <bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pb push_back
#define me memset
#define rep(a,b,c) for(int a=b;a<=c;++a)
#define per(a,b,c) for(int a=b;a>=c;--a)
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
using namespace std;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}
 
int n,m;
ll f[N];
 
int main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	f[1]=2,f[2]=4;
 
	cin>>n>>m;
 
	rep(i,3,max(n,m)) f[i]=f[i-1]%mod+f[i-2]%mod;
 
	cout<<(f[n]+f[m]-2)%mod<<'\n';
 
    return 0;
}
posted @ 2020-12-08 18:02  Rayotaku  阅读(83)  评论(0编辑  收藏  举报