Codeforces C. Ivan the Fool and the Probability Theory

題意

給你一個nmn * m的方格,問你有多少種方式可以將方格染成黑色和白色的,而且相鄰的方格最多有兩個顏色相同.

分析與解答

(非官方思路,想的比較繁瑣)
首先我們考慮只有一排的方格,定義dp數組如下:
dp[i][1][1]dp[i][1][1]爲前ii個第ii染色爲黑色,且第ii個爲單獨一個黑色的方案數
dp[i][0][1]dp[i][0][1]爲前ii個第ii染色爲白色,且第ii個爲單獨一個白色的方案數
dp[i][1][2]dp[i][1][2]爲前ii個第ii染色爲黑色,且第ii個爲連續兩個黑色的方案數
dp[i][0][2]dp[i][0][2]爲前ii個第ii染色爲白色,且第ii個爲連續兩個白色的方案數
轉移方程如下:
dp[i][1][1]=dp[i][0][1]+dp[i][0][2]dp[i][1][1] = dp[i][0][1] + dp[i][0][2]
dp[i][0][1]=dp[i][1][1]+dp[i][1][2]dp[i][0][1] = dp[i][1][1] + dp[i][1][2]
dp[i][1][2]=dp[i][1][1]dp[i][1][2] = dp[i][1][1]
dp[i][0][2]=dp[i][0][1]dp[i][0][2] = dp[i][0][1]
那麼第1i1*i方格的染色方案數爲ans[i]=dp[i][1][1]+dp[i][1][2]+dp[i][0][1]+dp[i][0][2]ans[i] = dp[i][1][1] + dp[i][1][2] + dp[i][0][1] + dp[i][0][2]
接下來考慮多排的問題.
我們注意到如果第一排出現兩個相同顏色的情況假設爲iii+1i + 1,我們考慮第二排這兩個位置的放置方法,如果我們放置任何一個與第一排顏色不同的那麼組成了三個顏色相同的連續的方塊,因此我們必須放置與第一排顏色不同的兩個方塊,同時我們考慮從這兩個位置向兩側延展,那麼i+2i+2位置,必須放置與第一排顏色不同的塊,i+3i+3位置也只能放置與第一排顏色不同的,以此類推,可得如果第一排有兩個連續的相同方塊第二排必須每個都與第一排顏色不同.這種情況下的方案數爲ans[m]2ans[m] - 2
如果第一排沒有連續兩個顏色相同的,我們按照同樣的推理方法我們可以得到,同一排相鄰兩個顏色必須不同.因此只要確定了第一列的放置就可以推出所有的排列方案,而第一列的放置不受約束,這種情況的方案數爲ans[n]ans[n]
綜上,最後的答案爲ans[m]2+ans[n]ans[m] - 2 + ans[n]

代碼

/*************************************************************************
	> File Name: 2019_10_20_3.cpp
	> Author: z472421519
	> Mail: 
	> Created Time: 2019年10月20日 星期日 17時45分14秒
 ************************************************************************/

#include <bits/stdc++.h>
#include <cstdio>
#include <cstring>
#define MAXN 100003
#define LL long long 
const LL mod = 1e9 + 7;
using namespace std;

LL mul(LL a,LL b)
{
    LL ans=0;
    while(b)
    {
        if(b&1) ans=(ans+a)%mod;
        b>>=1;
        a=(a%mod+a%mod)%mod;
    }
    return ans;
}
LL dp[MAXN][3][3];
LL sum[MAXN];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    dp[1][1][1] = dp[1][0][1] = 1ll;
    dp[1][1][2] = dp[1][0][2] = 0ll;
    sum[1] = 2ll;
    for(int i = 2;i <= 100000;i++)
    {
        dp[i][1][1] = (dp[i - 1][0][1] + dp[i - 1][0][2]) % mod;
        dp[i][0][1] = (dp[i - 1][1][1] + dp[i - 1][1][2]) % mod;
        dp[i][1][2] = dp[i - 1][1][1] % mod;
        dp[i][0][2] = dp[i - 1][0][1] % mod;
        sum[i] = (dp[i][1][1] + dp[i][1][2] + dp[i][0][1] + dp[i][0][2]) % mod;
    }
    //printf("%lld\n",sum[3]);
    cout << ((sum[m] - 2 + mod) + sum[n]) % mod;

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章