题目
题目描述
有一只「嘟嘟炎」,它在一个
n
×
m
n\times m
n×m 的
01
01
01 矩阵中随意跳动。它从第
1
1
1 行开始跳,最终跳到第
n
n
n 行,然后离开。
具体来说,它每次会从第 i ( i < n ) i\;(i<n) i(i<n) 行的第 a i a_i ai 列跳到第 i + 1 i+1 i+1 行的第 a i + 1 a_{i+1} ai+1 列,且满足 ∣ a i − a i + 1 ∣ ⩽ k |a_i-a_{i+1}|\leqslant k ∣ai−ai+1∣⩽k 。而「嘟嘟炎」跳过的位置就会被踩烂,也就是说,它走过的位置会从矩阵中移除,于是就会剩下一个 n × ( m − 1 ) n\times(m-1) n×(m−1) 的矩形。
现在请问,对于所有可能的 a i a_i ai,有多少种可能的不同剩余矩阵?两个矩阵不同,当且仅当存在某个位置,在两种情况中这个值不同。
数据范围与提示
n
m
⩽
1
0
6
nm\leqslant 10^6
nm⩽106 。
思路
首先,每一行的极长连续段中,删掉任意一个都是等效的。
区间 d p \tt dp dp 很容易做到。试着去优化,比如将状态限定为某个极长连续段的前缀或后缀?感觉也比较困难啊。
常用的 d p \tt dp dp 优化不行,就来点阴间的。众所周知 s a sa sa 做 “本质不同子串” 的方法是 n ( n + 1 ) 2 − ∑ i = 1 n − 1 h e i g h t ( i ) \frac{n(n+1)}{2}-\sum_{i=1}^{n-1}height(i) 2n(n+1)−∑i=1n−1height(i),为什么只是后缀排名相邻的字符串之间需要减去 l c p \rm lcp lcp 呢?这是因为一种特殊的性质:如果 s a s_a sa 某个前缀与 s b s_b sb 相同,那么二者排名之间的后缀与 s b s_b sb 也有公共前缀。这个是类似于 连通块 的性质:在树上,我们可以用 ∣ E ∣ = ∣ V ∣ − 1 |E|=|V|-1 ∣E∣=∣V∣−1 去重;在一维区间 S S S 上,用 ∑ x [ x ∈ S ∧ ( x + 1 ) ∈ S ] = ∣ S ∣ − 1 \sum_{x}[x\in S\wedge (x+1)\in S]=|S|-1 ∑x[x∈S∧(x+1)∈S]=∣S∣−1 也是同样的道理。
譬如某个子串,一定出现在 r a n k \rm rank rank 为某个区间的后缀中;某两种本质相同的 ⟨ a i ⟩ \langle a_i\rangle ⟨ai⟩,某层的可行出发点也构成区间。
于是考虑记
f
(
i
,
j
)
f(i,j)
f(i,j) 为
a
i
=
j
a_i=j
ai=j,可以随意确定
a
x
(
i
<
x
)
a_x\;(i<x)
ax(i<x),不同的剩余矩形数量;
g
(
i
,
j
)
g(i,j)
g(i,j) 则是
f
(
i
,
j
)
f(i,j)
f(i,j) 的所有可能剩余矩形和
f
(
i
,
j
−
1
)
f(i,j-1)
f(i,j−1) 的所有可能剩余矩形中,有多少个是相同的。那么容易写出转移
f
(
i
,
j
)
=
∑
x
=
j
−
k
j
+
k
f
(
i
+
1
,
x
)
−
∑
x
=
j
−
k
+
1
j
+
k
g
(
i
+
1
,
x
)
f(i,j)=\sum_{x=j-k}^{j+k}f(i+1,x)-\sum_{x=j-k+1}^{j+k}g(i+1,x)
f(i,j)=x=j−k∑j+kf(i+1,x)−x=j−k+1∑j+kg(i+1,x)
这个的原理跟
s
a
sa
sa 是一样的,即 “本质相同的
⟨
a
i
⟩
\langle a_i\rangle
⟨ai⟩ 在某一层的可行出发点构成区间”。
然而
g
(
i
,
j
)
g(i,j)
g(i,j) 是怎样转移的呢?其实也就是那些可以同时贡献到
f
(
i
,
j
)
f(i,j)
f(i,j) 和
f
(
i
,
j
−
1
)
f(i,j-1)
f(i,j−1) 的情况。直觉上,单看上面的
d
p
\tt dp
dp 式,你认为它就是
g
(
i
,
j
)
=
∑
x
=
j
−
k
j
+
k
−
1
f
(
i
+
1
,
x
)
−
∑
x
=
j
−
k
+
1
j
+
k
−
1
g
(
i
+
1
,
x
)
g(i,j)=\sum_{x=j-k}^{j+k-1}f(i+1,x)-\sum_{x=j-k+1}^{j+k-1}g(i+1,x)
g(i,j)=x=j−k∑j+k−1f(i+1,x)−x=j−k+1∑j+k−1g(i+1,x)
即那些在
d
p
\tt dp
dp 式中可以直接转移到
f
(
i
,
j
−
1
)
f(i,j-1)
f(i,j−1) 和
f
(
i
,
j
)
f(i,j)
f(i,j) 的。当然必须要
a
i
,
j
−
1
=
a
i
,
j
a_{i,j-1}=a_{i,j}
ai,j−1=ai,j 才行。
相信你和我有同样的疑惑:为什么 f ( i + 1 , j − 1 − k ) f(i+1,j-1-k) f(i+1,j−1−k) 贡献到 f ( i , j − 1 ) f(i,j-1) f(i,j−1) 和 f ( i + 1 , j + k ) f(i+1,j+k) f(i+1,j+k) 贡献到 f ( i , j ) f(i,j) f(i,j) 就不会重复呢?
……
重新审视一下已知的结论。到底什么是区间啊?所以考虑一个更形式化的证明:两个 ⟨ a i ⟩ \langle a_i\rangle ⟨ai⟩ 的本质相同,等价于它们在每一行上所删去的元素都属于同一个极长连续段。那么枚举究竟是哪些段(也就枚举了所有可能的剩余矩阵情况),求出 ⟨ a i ⟩ \langle a_i\rangle ⟨ai⟩ 的可能情况——注意是可行性判断,而非情况数。若 a i + 1 ∈ [ L , R ] a_{i+1}\in[L,R] ai+1∈[L,R] 可行,那么 a i ∈ [ L − k , R + k ] a_i\in[L-k,R+k] ai∈[L−k,R+k] 是必要的,还需与当前行所选择的极长连续段取交。于是 a i a_i ai 也属于某个区间,这是充要的。
那么 f ( i , j ) f(i,j) f(i,j) 等价于 a i a_i ai 的可行区间包含 j j j 的情况数,而 g ( i , j ) g(i,j) g(i,j) 就是同时包含 j − 1 j-1 j−1 和 j j j 的。计算方案数都是利用 “连通块容斥” 得出结果。
a i a_i ai 的区间同时包含 j − 1 j-1 j−1 和 j j j,反推回去,就是 a i + 1 ∈ [ j − k , j + k ) a_{i+1}\in[j-k,j+k) ai+1∈[j−k,j+k) 即可。而我们已经说过, ∑ x = l r f ( i , x ) − ∑ x = l + 1 r g ( i , x ) \sum_{x=l}^{r}f(i,x)-\sum_{x=l+1}^{r}g(i,x) ∑x=lrf(i,x)−∑x=l+1rg(i,x) 就代表了 a i a_i ai 的可行区间与 [ l , r ] [l,r] [l,r] 有交的情况数,所以就有了上文 g ( i , j ) g(i,j) g(i,j) 的递推式。
说白了就是那种问题:求 ∣ { x ∣ ∃ y , P ( x , y ) } ∣ \Big|\{x\;|\;\exists y,\;P(x,y)\}\Big| ∣∣∣{x∣∃y,P(x,y)}∣∣∣,转为求 ∑ x P ( x , y ) \sum_{x}P(x,y) ∑xP(x,y) 然后对 y y y 容斥。如果是指数级容斥即是 [NOI2021] 机器人游戏 一类,如果是 “连通块容斥” 即是 [十二省联考2019]希望 一类。
都是前缀和简单 d p \tt dp dp 转移,时间复杂度 O ( n m ) \mathcal O(nm) O(nm) 。
代码
没得代码。但是简单说一句:初状态是 f ( n , j ) = 1 f(n,j)=1 f(n,j)=1 而 g ( n , j ) = [ a n , j − 1 = a n , j ] g(n,j)=[a_{n,j-1}=a_{n,j}] g(n,j)=[an,j−1=an,j] 。