[XSY] 计数(DP,NTT,分治)
生活随笔
收集整理的這篇文章主要介紹了
[XSY] 计数(DP,NTT,分治)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
計數
- 考慮轉化題目,變為網格上有若干個點,要從(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??1?cnt(1,y),k?(y:初次走到的橫坐標為1的點的縱坐標)
=∑y=0a1?1ans(1,y+1)=\sum_{y=0}^{a_1-1}ans_{(1,y+1)}=∑y=0a1??1?ans(1,y+1)?(由歸納假設得出)
=∑y′=1a1ans(1,y′)=ans(0,1)=\sum_{y'=1}^{a_1}ans_{(1,y')}=ans_{(0,1)}=∑y′=1a1??ans(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??1?cnt(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??1?ans(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′=1a1??ans(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)
總結
以上是生活随笔為你收集整理的[XSY] 计数(DP,NTT,分治)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 四种不同的养护方式电脑如何养护模式
- 下一篇: 我电脑上安装的软件不多电脑总是安装一些没