Codeforces 1248C Ivan the Fool and the Probability Theory(推公式)

题意

一个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;
}
posted @ 2019-10-21 14:14  wrjlinkkkkkk  阅读(690)  评论(0编辑  收藏  举报