[XSY3343] 程序锁(DP)

XSY3343

先考虑如何判定一个填好的序列会不会gg:
∃ p , q , 使 s ′ [ p + 1 ] = t ′ [ q + 1 ] = − 1 \exist p,q,使s'[p+1]=t'[q+1]=-1 p,q,使s[p+1]=t[q+1]=1 ∑ i = 1 p s ′ [ i ] + ∑ j = 1 q t ′ [ j ] ≤ 0 \sum_{i=1}^{p}s'[i]+\sum_{j=1}^{q}t'[j]\leq 0 i=1ps[i]+j=1qt[j]0,则这个序列必gg。

那么我们只需找到 s u m s ′ = m i n s ′ [ p + 1 ] = − 1 { ∑ i = 1 p s ′ [ i ] } sum_{s'}=min_{s'[p+1]=-1}\{\sum_{i=1}^{p}s'[i]\} sums=mins[p+1]=1{ i=1ps[i]} s u m t ′ = m i n t ′ [ q + 1 ] = − 1 { ∑ j = 1 q t ′ [ j ] } sum_{t'}=min_{t'[q+1]=-1}\{\sum_{j=1}^{q}t'[j]\} sumt=mint[q+1]=1{ j=1qt[j]},判断 s u m s ′ + s u m t ′ sum_{s'}+sum_{t'} sums+sumt是否 ≤ 0 \leq0 0即可判断序列会不会gg。

为了方便,我们稍微转换一下条件,把 s ′ [ p + 1 ] , t ′ [ q + 1 ] s'[p+1],t'[q+1] s[p+1],t[q+1]也纳入 s u m s ′ , s u m t ′ sum_{s'},sum_{t'} sums,sumt中,即定义:
s u m s ′ = m i n s ′ [ p ] = − 1 { ∑ i = 1 p s ′ [ i ] } sum_{s'}=min_{s'[p]=-1}\{\sum_{i=1}^{p}s'[i]\} sums=mins[p]=1{ i=1ps[i]}
特别地,若 s ′ [ ] s'[] s[]全为1, s u m s ′ = ∑ i = 1 ∣ s ′ ∣ s ′ [ i ] sum_{s'}=\sum_{i=1}^{|s'|}s'[i] sums=i=1ss[i]
s u m t ′ = m i n t ′ [ q ] = − 1 { ∑ i = 1 q t ′ [ i ] } sum_{t'}=min_{t'[q]=-1}\{\sum_{i=1}^{q}t'[i]\} sumt=mint[q]=1{ i=1qt[i]}
特别地,若 t ′ [ ] t'[] t[]全为1, s u m t ′ = ∑ i = 1 ∣ t ′ ∣ t ′ [ i ] sum_{t'}=\sum_{i=1}^{|t'|}t'[i] sumt=i=1tt[i]

那么如果 s ′ [ ] , t ′ [ ] s'[],t'[] s[],t[]都不全为1,
有若 s u m s ′ + s u m t ′ ≤ − 2 sum_{s'}+sum_{t'}\leq-2 sums+sumt2,则序列必gg。
也即若 s u m s ′ + s u m t ′ ≥ − 1 sum_{s'}+sum_{t'}\geq-1 sums+sumt1,序列一定不会gg。

否则,若 s u m s ′ + s u m t ′ ≥ 0 sum_{s'}+sum_{t'}\geq0 sums+sumt0,序列一定不会gg。

然后考虑DP,正着DP很困难,考虑倒着DP,这样每次只会增加一个小前缀。

f i , j , k f_{i,j,k} fi,j,k表示填完 [ i , n ] [i,n] [i,n],这些位置相对于 i i i的前缀和中,以 − 1 -1 1结尾的最小前缀和 = j =j =j的方案数, k k k表示 j j j是否等于总和

如果 i − 1 i-1 i1位可以填 1 1 1,那么有 f i , j , 0 → f i − 1 , j + 1 , 0 , f i , j , 1 → f i − 1 , j + 1 , 1 f_{i,j,0}\rightarrow f_{i-1,j+1,0},f_{i,j,1}\rightarrow f_{i-1,j+1,1} fi,j,0fi1,j+1,0,fi,j,1fi1,j+1,1,因为在最前面加一个 1 1 1并不改变原来的最小前缀和

如果 i − 1 i-1 i1位可以填 − 1 -1 1,那么有 f i , j , 0 → f i − 1 , min ⁡ ( − 1 , j − 1 ) , 0 , f i , j , 1 → f i − 1 , min ⁡ ( − 1 , j − 1 ) , [ j ≤ 0 ] f_{i,j,0}\rightarrow f_{i-1,\min(-1,j-1),0},f_{i,j,1}\rightarrow f_{i-1,\min(-1,j-1),[j\le0]} fi,j,0fi1,min(1,j1),0,fi,j,1fi1,min(1,j1),[j0],因为增加了一个值为 − 1 -1 1的前缀和,所以原来 j > 0 j>0 j>0且最小前缀和 = j =j =j的方案会变为最小前缀和 = − 1 ≠ j − 1 =-1\ne j-1 =1=j1

两个序列分别DP后直接统计答案即可

总结:
倒着DP 和 对 s ′ , t ′ s',t' s,t两个序列分别DP 这两点太巧妙了%%%

猜你喜欢

转载自blog.csdn.net/Emma2oo6/article/details/120598400