題目大意:
一個$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 }
