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


    题意

    一个n*m的网格图,每个格子可以染黑色、白色,问你每个格子最多有一个相邻颜色相同的方案数
    n,m<=1e5

    思路

    我们先处理(1 imes m)的情况
    (f[i][j])为前(i)个格子,最后一个为(j)的方案数
    可以得到递推式(f[i][j]=f[i-1][jigoplus 1]+f[i-2][jigoplus 1])
    那么(1 imes 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;
    }
    
  • 相关阅读:
    kibana操作
    git使用入门
    ES增删改查
    MySQL&ES连接池
    java递归生成树结构的数据
    lambda新特性,对两组集合中相同的数据去重
    java8新特性 LocalDateTime,LocalDate ,LocalTime 使用,Period 获取时间差
    photoshop安装包
    java自定义异常及异常的抛出
    git回滚到任意版本
  • 原文地址:https://www.cnblogs.com/wrjlinkkkkkk/p/11713316.html
Copyright © 2020-2023  润新知