首先有一个很显然的状态:\(f_{i,j,k}\) 表示走到 \((i,j)\),乘积为 \(k\) 的方案数。
特别地,当 \(k = n\) 时表示乘积不小于 \(k\) 的方案数。
但是这样子是 \(O(rsn)\) 的。
如果我们把状态换一下,变成 \(f_{i,j,k}\) 表示走到 \((i,j)\),乘积至少乘 \(k\) 后不小于 \(n\) 的方案数。
看起来并没有什么变化……
但是,这样子的话,有用的 \(k\) 都形如 \(\lceil \dfrac n d \rceil\)。
类似数论分块,可以证明最多只有 \(O(\sqrt n)\) 种。
于是我们把有用的 \(k\) 重新标号(即离散化),然后跑 DP,同时滚动第一维(你要把第二维一起滚了也行 QwQ)。
这样子就得到了一个 \(O(rs \sqrt n)\) 的算法。
代码:
1 |
|