題意
一個n*m的網格圖,每個格子可以染黑色、白色,問你每個格子最多有一個相鄰顏色相同的方案數
n,m<=1e5
思路
我們先處理\(1 \times m\)的情況
設\(f[i][j]\)為前\(i\)個格子,最后一個為\(j\)的方案數
可以得到遞推式\(f[i][j]=f[i-1][j\bigoplus 1]+f[i-2][j\bigoplus 1]\)
那么\(1\times m\)的答案為\(f[m][0]+f[m][1]\)
引理
這題中的合法的染色圖相鄰兩行要么完全相同,要么完全相反
證明:
假設第\(i\)行和第\(i+1\)行部分相同,部分相反,設白色是\(0\),黑色是\(1\)
那么就存在一個位置\(j\),使得\(a[i+1][j]=a[i][j],a[i+1][j+1]!=a[i][j+1]\)(先不等后相等一樣)
因為這四個方格可選的顏色只有兩個,所以在\(a[i+1][j+1]\)和\(a[i][j+1]\)中一定有一個和\(a[i+1][j]\)與\(a[i][j+1]\)相同
也就是說,這四個方格中出現了三個一樣的顏色,無論怎么組合都不滿足題意,
所以不存在部分相同部分相反,引理得證
有了以上結論,我們可以可以找"什么時候完全相同,什么時候完全相反"了
可以發現,當一行里存在連續兩個連續一樣的顏色的時候,下一行一定與該行相反
也就是說,如果確定了第一行,里面有兩個連續一樣的顏色,對答案的貢獻為1
第一行的這種情況方案數為\(f[m][0]+f[m][1]-2\)
而排除的這兩種,就是第一行為\(10101010..\)和\(01010101..\)兩種方案
由於引理的存在,我們可以知道,當每一行的第一個元素確定的時候,我們就確定了這行跟上一行完全相同還是相反
所以這種情況的貢獻就是第一列的合法方案數,即\(f[n][0]+f[n][1]\)
終上所述,答案為\(f[m][0]+f[m][1]+f[n][0]+f[n][1]-2\)
代碼
ll n,m;
ll f[maxn][3];
ll F[maxn];
int main(){
scanf("%lld %lld", &n, &m);
f[1][0]=f[1][1]=1;
f[2][0]=f[2][1]=2;
F[1]=2;F[2]=4;
for(int i = 3; i <= max(n,m); i++){
f[i][1]=(f[i-1][0]+f[i-2][0])%mod;
f[i][0]=(f[i-1][1]+f[i-2][1])%mod;
F[i]=(f[i][0]+f[i][1])%mod;
}
printf("%lld",(F[n]+F[m]-2+mod)%mod);
return 0;
}