link
其实是我之前写的一篇博客的推广
大意:
一个阶梯型,第
i
i
i行有
⌈
i
/
2
⌉
∗
2
\left \lceil i/2 \right \rceil*2
⌈i/2⌉∗2个方块,总共有n行。在其中给定
m
m
m个点无法经过,求从左上角到右下角的方案数。其中每次移动只能向右或向下
N
≤
2.5
e
5
,
M
≤
50
N\leq 2.5e5,M\leq 50
N≤2.5e5,M≤50
思路:
一个比较显然的思路是把原图还原为
n
×
n
n\times n
n×n的矩阵,然后再添加
n
−
2
n-2
n−2个障碍
(
i
,
⌈
i
/
2
⌉
∗
2
+
1
)
(i,\left \lceil i/2 \right \rceil*2+1)
(i,⌈i/2⌉∗2+1),这样就还原成了经典模型,可以直接用容斥来做。
还是将障碍按横纵坐标排个序,同时不妨将终点也放入
S
S
S中,显然排序后它会是最后一个点
令
S
S
S表示障碍的集合,
d
p
i
dp_i
dpi表示从起点到第i个障碍,中间不经过其它障碍的方案数,
w
i
w_i
wi表示S中的第i个障碍,
g
(
⋅
)
g(\cdot)
g(⋅)表示两点之间的所有最短路的方案数(不考虑中间是否经过障碍)
不难得到一个非常naive的式子:
d
p
i
=
g
(
(
1
,
1
)
,
w
i
)
−
∑
j
<
i
g
(
j
,
i
)
d
p
j
a
n
s
=
d
p
∣
S
∣
+
1
dp_i=g((1,1),w_i)-\sum_{j<i}g(j,i)dp_j\\ ans = dp_{|S|+1}
dpi=g((1,1),wi)−j<i∑g(j,i)dpjans=dp∣S∣+1
但是这样做的时间复杂度是
O
(
(
n
+
m
)
2
O((n+m)^2
O((n+m)2,尝试优化
首先对式子换一个好看点的形式:
令
f
i
=
d
p
i
f_i=dp_i
fi=dpi,有
f
i
=
−
(
g
(
(
1
,
1
)
,
w
i
)
−
∑
j
<
i
g
(
j
,
i
)
d
p
j
)
=
−
g
(
(
1
,
1
)
,
w
i
)
−
∑
j
<
i
g
(
j
,
i
)
f
j
=
∑
j
=
0
i
−
1
g
(
w
j
,
w
i
)
f
j
f_i=-(g((1,1),w_i)-\sum_{j<i}g(j,i)dp_j)=-g((1,1),w_i)-\sum_{j<i}g(j,i)f_j =\sum_{j=0}^{i-1}g(w_j,w_i)f_j
fi=−(g((1,1),wi)−j<i∑g(j,i)dpj)=−g((1,1),wi)−j<i∑g(j,i)fj=j=0∑i−1g(wj,wi)fj
这里我们把起点也加入了
S
S
S中,并令它为第0个点(显然合理)
从而
f
i
=
∑
j
=
0
i
−
1
g
(
w
j
,
w
i
)
f
j
,
0
≤
i
≤
∣
S
∣
+
1
a
n
s
=
−
f
∣
S
∣
+
1
f_i=\sum_{j=0}^{i-1}g(w_j,w_i)f_j,0\leq i\leq |S|+1\\ ans=-f_{|S|+1}
fi=j=0∑i−1g(wj,wi)fj,0≤i≤∣S∣+1ans=−f∣S∣+1
注意到障碍总共可以分为两类:
- 题目里原本就在的,数量为O(M)
- 我们新加的,数量为O(N)
而M其实并不大,第一类的点最多带来
O
(
M
(
N
+
M
)
)
O(M(N+M))
O(M(N+M))的复杂度,这部分我们可以直接暴力。此时我们需要优化的部分就是后者内部的
O
(
N
×
N
)
O(N\times N)
O(N×N)的复杂度
对第二类点换一种记法:
w
i
,
1
=
(
2
i
−
1
,
2
i
+
1
)
w
i
,
2
=
(
2
i
,
2
i
+
1
)
w_{i,1}=(2i-1,2i+1)\\ w_{i,2}=(2i,2i+1)
wi,1=(2i−1,2i+1)wi,2=(2i,2i+1)
我们先假设第一类点的贡献已经统计完了(
w
i
,
1
,
w
i
,
2
w_{i,1},w_{i,2}
wi,1,wi,2之间的贡献也可以在这里算好,复杂度
O
(
N
)
O(N)
O(N)),那么此时
f
i
,
1
=
f
i
,
1
−
∑
j
<
i
f
j
,
1
g
(
w
j
,
1
,
w
i
,
1
)
+
f
j
,
2
g
(
w
j
,
2
,
w
i
,
1
)
f
i
,
2
=
f
i
,
2
−
∑
j
<
i
f
j
,
1
g
(
w
j
,
1
,
w
i
,
2
)
+
f
j
,
2
g
(
w
j
,
2
,
w
i
,
2
)
f_{i,1} =f_{i,1}- \sum_{j<i}f_{j,1}g(w_{j,1},w_{i,1})+f_{j,2}g(w_{j,2},w_{i,1})\\ f_{i,2} =f_{i,2}- \sum_{j<i}f_{j,1}g(w_{j,1},w_{i,2})+f_{j,2}g(w_{j,2},w_{i,2})\\
fi,1=fi,1−j<i∑fj,1g(wj,1,wi,1)+fj,2g(wj,2,wi,1)fi,2=fi,2−j<i∑fj,1g(wj,1,wi,2)+fj,2g(wj,2,wi,2)
注意到这里
g
(
⋅
)
g(\cdot)
g(⋅)的含义其实非常好求,因为它不需要考虑中间经过的点的类型,我们把它写出来
g
(
w
j
,
2
,
w
i
,
1
)
=
(
4
(
i
−
j
)
−
1
2
(
i
−
j
)
)
g
(
w
j
,
1
,
w
i
,
1
)
=
g
(
w
j
,
2
,
w
i
,
2
)
=
(
4
(
i
−
j
)
2
(
i
−
j
)
)
g
(
w
j
,
1
,
w
i
,
2
)
=
(
4
(
i
−
j
)
+
1
2
(
i
−
j
)
)
g(w_{j,2},w_{i,1}) = \binom{4(i-j)-1}{2(i-j)}\\ g(w_{j,1},w_{i,1}) = g(w_{j,2},w_{i,2})= \binom{4(i-j)}{2(i-j)}\\ g(w_{j,1},w_{i,2}) = \binom{4(i-j)+1}{2(i-j)}
g(wj,2,wi,1)=(2(i−j)4(i−j)−1)g(wj,1,wi,1)=g(wj,2,wi,2)=(2(i−j)4(i−j))g(wj,1,wi,2)=(2(i−j)4(i−j)+1)
不难发现它们其实都可以表示成
(
i
−
j
)
(i-j)
(i−j)的函数,那么显然上述式子就可以用fft来优化了,从而这部分的时间复杂度来到了
O
(
N
l
o
g
2
N
)
O(Nlog^2N)
O(Nlog2N)
所以总体复杂度为
O
(
M
(
N
+
M
)
+
N
l
o
g
2
N
)
O(M(N+M)+Nlog^2N)
O(M(N+M)+Nlog2N)
over
(退役口胡选手不想敲代码…
那么理论上这种题目也是可以推广的,任意形状的阶梯型我们都可以用同样的复杂度来求解,哪怕有多条边有阶梯形也没有关系(只要中间没有洞)