CF C.Ivan the Fool and the Probability Theory【思維·構造】


題目傳送門

題目大意:

一個$n*m$的網格圖,每個格子可以染黑色、白色,問每個格子最多有一個相鄰格子顏色相同的塗色方案數
$n,m<=1e5$

分析:

首先,考慮到如果有兩個相鄰的格子顏色相同,那么這兩行/列的格子狀態就確定了。比如:

 

 

 在中間兩個愛心格子被確定的情況下,第二列和第三列的塗色情況就已經被確定了。實際上,第一列和第四列塗的顏色也確定了。(最后這句話我們留着待會兒分析)

 

 

 同理,在中間兩個星星確定的時候,第二行和第三行的塗色情況也唯一確定。實際上,第一行和第四列塗的顏色也確定了。

 


假如說在一個方格中,既有橫着出現的兩個連續的一樣顏色的格子,也有豎着出現的兩個連續的一樣顏色的格子,就像這樣:

 

 

 

 

 

 

 

那么一定會產生矛盾,無論怎么挪都會產生矛盾。(橙色的部分是既需要用灰色,也需要用藍色塗的格子,是矛盾的地方)

所以,在一種着色方案中,這種相鄰兩個顏色一樣的情況只會在一個方向中出現,我們只需要考慮一個方向那么多行的方案數,另外一個方向的同理就好。

 


 

如果已經確定相鄰兩個顏色一樣的格子出現的方向(為方便討論,下面我們假設這兩個格子是豎着的),那么每一行的格子顏色一定是交錯的,兩行之間要么一樣,要么顏色相反,而且顏色一樣的不能連着出現3次及以上。

在第一行確定的情況下,如果要求每一個格子的每個相鄰格子的顏色都和他不一樣,那么這是一個棋盤染色,就唯一確定了。

但是,按照這道題的條件來說的話,后面的格子可以有兩行,也可以只有一行。(就是一次性確定兩行或一次性確定一行)

Like this:

 

 

 

 

 

 設$f[i]$表示鋪到第$i$行(前$i$行)的方案總數,那么遞推式就是$f[i]=f[i-1]+f[i-2]$

(初始化$f[0]=1$是一開始就是兩行連着一樣的情況)

答案就是$f[n]$。

然后,還有相鄰兩個顏色一樣的格子是豎着的,方案數就是$f[m]$,這兩類在前面已經說過沒有交集,答案就是$f[n]+f[m]$

然后,棋盤染色的情況在兩種情況中都被計算了,所以答案要減1。

最后,黑白顏色可以反過來,所以乘2.

做完了,$Nice!$

 1 /*
 2 ID: Starry21               
 3 */ 
 4 #include<iostream>
 5 #include<string>
 6 #include<cstdio>
 7 #include<cstring>
 8 #include<map>
 9 #include<algorithm>
10 using namespace std;
11 #define N 100005
12 #define ll long long
13 #define MOD 1000000007
14 int n,m;
15 ll f[N];
16 int main()
17 {
18     scanf("%d %d",&n,&m);
19     f[0]=f[1]=1;
20     for(int i=2;i<=max(n,m);i++)
21         f[i]=(f[i-1]+f[i-2])%MOD;
22     printf("%lld\n",2*((f[n]+f[m])%MOD-1+MOD)%MOD);
23     return 0;
24 }
代碼賊短

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM