[jzoj]5965. 【NOIP2018提高组D2T2】填数游戏(推式子)

本文探讨了一种特殊的棋盘填充问题,目标是在限定条件下填充棋盘,使任意两条从原点到特定点的路径字典序相对小。文章详细分析了解决方案,包括对棋盘填充值的限制条件,以及通过分类讨论得出的解答方法。适用于n≤8,m≤10^6的范围。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Problem

  • 给定你一个n⋅mn·mnm网格棋盘,要求用0/10/10/1填充每一个格子.

  • 使得任意两条从原点(0,0)(0,0)(0,0)(n−1,m−1)(n-1,m-1)(n1,m1)的不完全相交路径,先走右方向(字典序大)的路径的010101路径字典序相对小.

  • 求方案数.

Data constraint

  • n≤8,m≤106n\le 8, m \le 10^6n8,m106

Solution

  • 其实这题可以不用DPDPDP.

  • 显然对于棋盘上的某一种填法AAA,满足∀i∈(0,n),j∈(0,m),Ai,j≥Ai−1,j+1\forall i\in(0,n),j\in(0,m),A_{i,j}\ge A_{i-1,j+1}i(0,n),j(0,m),Ai,jAi1,j+1

  • 且显然如果当Ai,j=Ai−1,j+1A_{i,j}=A_{i-1,j+1}Ai,j=Ai1,j+1时,(i,j+1)→(n,m)(i,j+1)\rightarrow(n,m)(i,j+1)(n,m)形成一个封闭局面,这个局面的每条对角线上的数必须相同,这样是为了保证(i,j+1)→(n,m)(i,j+1)\rightarrow(n,m)(i,j+1)(n,m)的每条路径相同.

  • 那么现在就可以分类讨论了:

    • (0,1),(1,0)(0,1),(1,0)(0,1),(1,0)两格相同:

      • 这种情况下,只需要使得(1,1)→(n,m)(1,1)\rightarrow(n,m)(1,1)(n,m)的所有对角线上数字相同.

      • 同时第一列和第一行会受其影响,仔细推一波式子可以搞定.

      • 答案形如4x∗3y∗2z4^x*3^y*2^z4x3y2z.

      • 这是最简单的情况。

    • (0,1),(1,0)(0,1),(1,0)(0,1),(1,0)两格不同:

      • (0,2),(1,1),(2,0)(0,2),(1,1),(2,0)(0,2),(1,1),(2,0)相同:

        • 这一种情况也相对简单,也是一波式子可以搞定的.

        • 这是次简单的情况,其实与第一种情况完全类似,答案的形式也是一样的.

      • (0,2),(1,1),(2,0)(0,2),(1,1),(2,0)(0,2),(1,1),(2,0)其中一对相同:

        • 不难发现(1,1)(1,1)(1,1)(2,0)(2,0)(2,0)(0,2)(0,2)(0,2)相同是等价的.

        • 不妨假设(1,1),(2,0)(1,1),(2,0)(1,1),(2,0)相同.

        • f[i]f[i]f[i]表示到第iii条对角线上时,在前两行的第i−1i-1i1斜线上及以前有过“配对成功”的方案数。

        • “配对成功” 是指在最上边两行中,第二行的某一格与其斜上方的格相同,称之为配对成功。

        • 因为一旦配对成功,接下来第二行的填数就会有限制.

        • 当第一行与第二行全部没有配对成功时,当前的一条对角线实际上有555种填法,而当iii条对角线配对成功时,实际上只有444种填法.

        • 那么考虑一下转移就可以写出:f[i]=f[i−1]∗4+4∗5f[i] = f[i - 1] * 4 + 4 * 5f[i]=f[i1]4+45

        • 表示的含义是:

        • (在i−2i-2i2条斜线上以前就匹配成功的方案f[i−1]f[i-1]f[i1]) *(当前第iii条对角线的444种填法) + (i−1i-1i1条斜线第一次匹配成功444种填法) * (当前第iii条对角线因不受任何影响所以有555种填法.)

  • 这样就可以计算出当n=mn=mn=m的答案了.

  • m=n+1m = n + 1m=n+1时,前两种分类讨论是很容易继续推广的,关键是第三种 分类讨论应当如何推广.

  • 不妨画一下图,我们发现,实质上答案是ANS=(4+4∗4+(f[n]∗3+4∗3)∗2)∗2n−1ANS=(4 + 4 * 4 + (f[n] * 3 + 4 * 3) * 2) * 2^{n-1}ANS=(4+44+(f[n]3+43)2)2n1

  • 至于为什么也是按上面第三种分类讨论一样,根据最后一条对角线是否匹配成功进行讨论.

  • 而当m=n+1m=n+1m=n+1时,(2,0),(1,1),(0,2)(2,0),(1,1),(0,2)(2,0),(1,1),(0,2)哪两个相同是会有影响的,根据上面的推法,也不难推出另外一种的答案实质上是ANS=(f[n]∗3+4∗5)∗2nANS = (f[n] * 3 + 4 * 5) * 2^nANS=(f[n]3+45)2n

  • 并且继续仔细推式子后可以发现当m>n+1m>n+1m>n+1时,mmm每加一,答案会乘333.

  • 于是时间复杂度是O(n+log2m)O(n+log_2m)O(n+log2m),可以矩阵转移做到O(logn+logm)O(log_n+log_m)O(logn+logm)

  • 参考代码:

F(i, 1, n - 4)
	f[i + 1] = (4 * 5 + f[i] * 4) % Mo; // 4表示上一条对角线第一次配对成功
ans = 2 * (3 + 4 * 3 + f[n - 3] * 2) * ksm(2, n - 1); // n==m 时的
a1 = ksm(4, n - 2) * ksm(2, n + 1) % Mo; //第一种情况
a2 = 5 * ksm(4, n - 4) * ksm(2, n + 1) % Mo; //第二种情况
if (n == m) { printf("%d", (ans + a1 + a2) % Mo); return 0; } 

ANS1 = (4 + 4 * 4 + (f[n - 3] * 3 + 4 * 3) * 2) * ksm(2, n - 1) % Mo; // n+1==m的第一种情况
ANS2 = (f[n - 3] * 3 + 4 * 5) * ksm(2, n) % Mo; //n+1==m的第二种情况
printf("%d", ((((a1 + a2) * 3 + ANS1 + ANS2) % Mo) * ksm(3, m - n - 1)) % Mo);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值