海底积木赛题解

题解

把每一个字符分别对应一个数字

在这里假定B对应0,W对应1,R对应2

假定两个相邻积木的值为 d 1 , d 2 d_1,d_2 d1,d2

那他们上面的数字就为 ( 3 − d 1 − d 2 + 3 ) m o d 3 (3-d_1-d_2+3)mod3 (3d1d2+3)mod3

故最下方的格子会将它的值向上传递,直到传到最上方

类似于一个递推的思想

每个格子对上方的格子都会有一个贡献值

于是可以计算出这个最下方每个格子对最上方格子的贡献值

如下图所示

海底积木赛题解_第1张图片

问题转化为求每个格子的贡献值为多少,即最上方格子的系数为多少

通过对每个格子的分析图,不难看出,每个点对它上方的点的贡献值,就是它能只向上方走时,能到达这个点的路径条数

于是就变成了一道熟悉的递推题,对于一个二维图,求原点到某一点的路径条数

但这种题目还有另外一种解题方法,即用组合数学来求解,假设总共要走n步,要向左上方走m步,那么路径条数就为 C n m C_n^m Cnm

如果直接用逆元去求解组合数问题,会因为需要取模的数字过小(只有3),在求阶乘时严重改变了它原来的值,而导致出错

所以使用另一种求组合数的方法,Lucas定理,具体证明过程可以自行搜索或参考算阶

通过Lucas定理就可以将大的组合数转化为小的组合数,而求解小的组合数时,又可以用求逆元的方法,因为p=3,故p-2=1,所以可以直接省略快速幂的过程,返回 j c n ∗ j c m ∗ j c n − m jc_n*jc_m*jc_{n-m} jcnjcmjcnm的值

另外,从图中可以看出,当层数为偶数时,系数为相反数,所以需要进行一下特殊修改

注意:防止出错,0的阶乘在代码中定义为1

你可能感兴趣的:(AtCoder,算法)