计数
- 考虑转化题目,变为网格上有若干个点,要从(0,0)(0,0)(0,0)走到(n,an+1)(n,a_{n+1})(n,an+1) ,每一步只能往右走一步或往上走一步,且若当前在(i,j)(i,j)(i,j) ,必须满足0≤j≤ai+10\leq j\leq a_{i+1}0≤j≤ai+1,其中an+1=ana_{n+1}=a_nan+1=an 。要对每个kkk求出有多少条恰走过kkk次形如(i,ai+1)→(i+1,ai+1)(i,a_{i+1})\to(i+1,a_{i+1})(i,ai+1)→(i+1,ai+1)的步的路径数。
上图是n=9的一种情况,题目相当于求在规定只能向右走/向上走的情况下,有多少条从s到t的、不跨越红线(可与红线重叠)的、恰走过kkk次形如(i,ai+1)→(i+1,ai+1)(i,a_{i+1})\to(i+1,a_{i+1})(i,ai+1)→(i+1,ai+1)的步的路径。
- 不考虑最后的那个怪异条件,这就是道小奥题(当时用标数法解决)
- 考虑转化一下最后的条件:
引理: 对于其中一个kkk,其答案等价于从(k,1)(k,1)(k,1)走到(n,an)(n,a_n)(n,an)的方案数。
证明: 对nnn归纳,在n=1n=1n=1时显然成立。在n>1n>1n>1时考虑初次走到的横坐标为1的点的纵坐标是什么。
记cnt(i,j),kcnt_{(i,j),k}cnt(i,j),k表示从(i,j)(i,j)(i,j)到(n,an+1)(n,a_{n+1})(n,an+1)的、恰走过kkk次形如(i,ai+1)→(i+1,ai+1)(i,a_{i+1})\to(i+1,a_{i+1})(i,ai+1)→(i+1,ai+1)的步的符合条件的路径数,
ans(i,j)ans_{(i,j)}ans(i,j)表示从(i,j)(i,j)(i,j)到(n,an+1)(n,a_{n+1})(n,an+1)的,不考虑走了几次形如(i,ai+1)→(i+1,ai+1)(i,a_{i+1})\to(i+1,a_{i+1})(i,ai+1)→(i+1,ai+1)的步的符合条件的路径数。
若k=0,k=0,k=0,
cnt(0,0),k=∑y=0a1−1cnt(1,y),kcnt_{(0,0),k}=\sum_{y=0}^{a_1-1}cnt_{(1,y),k}cnt(0,0),k=∑y=0a1−1cnt(1,y),k(y:初次走到的横坐标为1的点的纵坐标)
=∑y=0a1−1ans(1,y+1)=\sum_{y=0}^{a_1-1}ans_{(1,y+1)}=∑y=0a1−1ans(1,y+1)(由归纳假设得出)
=∑y′=1a1ans(1,y′)=ans(0,1)=\sum_{y'=1}^{a_1}ans_{(1,y')}=ans_{(0,1)}=∑y′=1a1ans(1,y′)=ans(0,1)
若k>0,k>0,k>0,
cnt(0,0),k=∑y=0a1−1cnt(1,y),k+cnt(1,a1),k−1cnt_{(0,0),k}=\sum_{y=0}^{a_1-1}cnt_{(1,y),k}+cnt_{(1,a_1),k-1}cnt(0,0),k=∑y=0a1−1cnt(1,y),k+cnt(1,a1),k−1
=∑y=0a1−1ans(k+1,y+1)+ans(k,a1+1)=\sum_{y=0}^{a_1-1}ans_{(k+1,y+1)}+ans_{(k,a_1+1)}=∑y=0a1−1ans(k+1,y+1)+ans(k,a1+1)
=∑y′=1a1ans(k+1,y′)+ans(k,a1+1)=ans(k,1)=\sum_{y'=1}^{a_1}ans_{(k+1,y')}+ans_{(k,a_1+1)}=ans_{(k,1)}=∑y′=1a1ans(k+1,y′)+ans(k,a1+1)=ans(k,1) - 考虑如何求ans(k,1)ans_{(k,1)}ans(k,1):
像我前面说的,小奥标数法肯定正确,但复杂度太低了,我们必须另辟蹊径。ans(k,1)ans_{(k,1)}ans(k,1)难求是因为红线的限制,否则在一个普通的矩形网格内从(i,j)(i,j)(i,j)到(i+a,j+b)(i+a,j+b)(i+a,j+b)(a≥0,b≥0)(a\geq0,b\geq0)(a≥0,b≥0)的合法路径数可用Ca+baC_{a+b}^{a}Ca+ba算出
- 因此我们考虑将题目不规则的网格活动区间划分成数个矩形,分治求解。
- 最自然的想法是每一刀都竖着切,直接划分为若干个竖直的矩形:
但这样太慢了,肯定会T
- 考虑竖切、横切交替进行,把原区间大概划分成这样:
可以证明复杂度是正确的
- 考虑具体如何分治:
假设我们切完后把原区间分为了右上、右下矩形、左下三个部分。
题目所求为浅紫线上的点到(n,an+1)(n,a_{n+1})(n,an+1),只向上/向右走、不跨越红线的路径数。
- 右下矩形部分粉紫线上的点到(n,an+1)(n,a_{n+1})(n,an+1),要么经右下矩形部分的橙线上的点,要么经深紫线上的点,所以
该段粉紫线上某点到(n,an+1)的路径数=∑粉紫线上该点到右下矩形部分的橙线上某点的路径数×右下矩形部分的橙线上该点到(n,an+1)的路径数+∑粉紫线上该点到深紫线上某点的路径数×深紫线上该点到(n,an+1)的路径数该段粉紫线上某点到(n,a_{n+1})的路径数=\sum粉紫线上该点到右下矩形部分的橙线上某点的路径数\times 右下矩形部分的橙线上该点到(n,a_{n+1})的路径数+\sum粉紫线上该点到深紫线上某点的路径数\times 深紫线上该点到(n,a_{n+1})的路径数该段粉紫线上某点到(n,an+1)的路径数=∑粉紫线上该点到右下矩形部分的橙线上某点的路径数×右下矩形部分的橙线上该点到(n,an+1)的路径数+∑粉紫线上该点到深紫线上某点的路径数×深紫线上该点到(n,an+1)的路径数 - 又因为右下部分为矩形,所以粉紫线上某点到右下矩形部分的橙线上某点的路径数、粉紫线上某点到深紫线上某点的路径数均可用组合数O(1)O(1)O(1)求出。
- 在分治的第一层,橙线上的点到(n,an+1)(n,a_{n+1})(n,an+1)的路径数是已知的(均为1),但深紫线上的点到(n,an+1)(n,a_{n+1})(n,an+1)的路径数未知。所以我们先递归右上部分,求出深紫线上的点到(n,an+1)(n,a_{n+1})(n,an+1)的路径数。
- 如此,我们便可以更新粉紫线上的点到(n,an+1)(n,a_{n+1})(n,an+1)的路径数
- 左下部分浅紫线上的点到(n,an+1)(n,a_{n+1})(n,an+1)的路径数可以通过递归左下部分求出,但为此我们必须先求出黄线上的点到(n,an+1)(n,a_{n+1})(n,an+1)的路径数:
黄线上的点到(n,an+1)(n,a_{n+1})(n,an+1),要么经右下矩形部分的橙线上的点,要么经深紫线上的点,所以
黄线上某点到(n,an+1)的路径数=∑黄线上该点到右下矩形部分的橙线上某点的路径数×右下矩形部分的橙线上该点到(n,an+1)的路径数+∑黄线上该点到深紫线上某点的路径数×深紫线上该点到(n,an+1)的路径数黄线上某点到(n,a_{n+1})的路径数=\sum黄线上该点到右下矩形部分的橙线上某点的路径数\times 右下矩形部分的橙线上该点到(n,a_{n+1})的路径数+\sum黄线上该点到深紫线上某点的路径数\times 深紫线上该点到(n,a_{n+1})的路径数黄线上某点到(n,an+1)的路径数=∑黄线上该点到右下矩形部分的橙线上某点的路径数×右下矩形部分的橙线上该点到(n,an+1)的路径数+∑黄线上该点到深紫线上某点的路径数×深紫线上该点到(n,an+1)的路径数 - 黄线和粉紫线的更新都可以用NTT搞出来。总时间复杂度O(nlog2n)O(nlog^2n)O(nlog2n)
ps:为了保证不重不漏,当我说"某点到××\times\times××线上某点的路径数"时,那么所到达的该线上的点是所有该线上的点中最先被到达的。
以下图为例,某点到橙线上的(x,y)(x,y)(x,y)的路径数,统计的路径的最后一步必为(x−1,y)→(x,y)(x-1,y)\to(x,y)(x−1,y)→(x,y)