目錄html
有一個長爲 \(n\) 的序列 \(a_0,a_1,\cdots, a_{n - 1}\) ,給你三個參數 \(X,Y,Z\) 。git
定義一個好的序列知足 存在 \(0\le x < y < z < w \le n\) 使得
\[ \begin{align} \sum_{i = x}^{y - 1} a_i &= X\\ \sum_{i = y}^{z - 1} a_i &= Y\\ \sum_{i = z}^{w - 1} a_i &= Z \end{align} \]
問知足條件的序列有多少個。(對於 \(10^9 + 7\) 取模)app
\(3 \le n \le 40, 1 \le X,Z \le 5, 1 \le Y \le 7\) 且 \(1 \le a_i \le 10, a_i \in \mathbb{N^{+}}\) 。優化
一道很妙的題qwqspa
一開始以爲是個思博題,而後發現怎麼正向計數都會算重。指針
後來去看了下題解,原來能夠轉化成 \(10^n -\) 不合法的序列數,這樣就不會記重了。code
但這樣轉化後如何記呢?數據範圍十分地小,能夠狀壓 \(dp\) 。htm
具體來講就是把一個 \(a_i\) 拆成一個 \(1\) 和 \(a_i - 1\) 個 \(0\) 。blog
好比 \(5\) 會被拆成 \(\underline{10000}\) 。排序
而後咱們就能夠把以前填的數順次拼起來了。
這樣有什麼好處呢?不難發現若是一段連續的和爲 \(S\) ,那麼 \(S\) 轉化後的集合 會是 連續一段轉化後拼起來構成的集合的 子集 。
好比 \(2 + 4 = 6\) ,就有 \(\underline {100000} \in \underline{10} + \underline{1000} = \underline{101000}\) 。
那麼咱們只要對於每一個位置狀壓前 \(X + Y + Z = 17\) 位就好了,一開始 \(X,Y,Z\) 壓成的狀態順次拼到一塊兒的狀態,就是全部不可行的狀態的本身。
枚舉當前填到哪一位,以及狀態,再枚舉這位填什麼就好了,複雜度就是 \(O(10n2^{X+Y+Z})\) 的。
要求連續和很小的時候也能夠巧妙狀壓,注意看數據範圍。
戳這個 連接 ,好寫的很。
一開始會有個空串 \(S\) ,有三個操做。
而後你會進行 \(n\) 次操做,給你最後的串 \(S\) ,問有多少種不一樣的操做序列知足條件。(對於 \(10^9 + 7\) 取模)
\(n \le 5000, 1 \le |S| \le n\)
一開始隨便想了個 \(O(n^3)\) 的暴力,就是令 dp[i][j][k]
爲當前進行了 \(i\) 次操做,串長爲 \(j\) ,第一個失配的地方在 \(k\) 的操做方案數,對於當前進行什麼操做分開考慮就好了。
其實正解很思博,咱們以前那個 dp
第三維是沒有必要的,由於咱們發現串的形態是不會影響答案的,因此就令 dp[i][j]
爲進行了 \(i\) 次操做,串長爲 \(j\) 的方案數。
最後答案就是 \(\displaystyle \frac{dp[n][len]}{2^{len}}\) ,由於最後每一個串對應的方案數都是同樣的,總共有 \(2^{len}\) 個串,這樣就是 \(O(n ^ 2)\) 的了。
其實能夠繼續優化,怎麼考慮計數呢,由於最後的串長要剛好爲 \(len\) ,咱們能夠轉化成至多爲 \(len\) 的答案減去至多爲 \(len - 1\) 的答案。
咱們假設 \(f(x)\) 爲串長至多爲 \(x\) 的答案,那麼表達出來就是:
\[ f(x) = \sum_{i = 0}^{n} [i - (n - i) \le x] ({n \choose i} - {n \choose i - (x + 1)}) \times 2^{i} \]
也就是咱們考慮在 \(n\) 個操做中有 \(i\) 個操做爲在後面添加字符,剩餘 \(n - i\) 個操做爲退格操做。
\([i - (n - i) \le x]\) 意味着全部退格和添加字符操做 所有抵消 後串長不超過 \(x\) ,這是必要的條件。
\(\displaystyle {n \choose i}\) 是全部可能添加和退格操做的排列,\(-\displaystyle {n \choose i - (x + 1)}\) 是全部最後串長會超過 \(x\) 的狀況。
爲何會出現超過 \(x\) 的狀況呢?由於會有好一些退格操做都不會產生做用,不會產生做用的若是有 \(i - (x + 1)\) 及以上個,那麼就是不行的。
不難發現,把其中不會消除的 \(i - (x + 1)\) 退格操做放在排列在 \(n\) 個總操做之中的任意一個地方,對應僅對應且僅對應一組不合法的解。
最後發現每一個添加數字的操做會對應兩個操做,因此還要乘上 \(2^i\) 。
預處理了階乘和階乘逆元后就能夠作到 \(O(n)\) 的複雜度啦。
對於求最後要求形態惟一的題,能夠考慮有多少個形態的方案數是和它如出一轍的,最後除去那麼多就好了,一般能夠下降一維的複雜度。
\(O(n^3):\) 代碼戳這裏。
\(O(n^2):\) 代碼戳這裏。
\(O(n):\) 代碼戳這裏。
給你兩個數 \(n, s\) ,找出一個最小的數 \(b\) 使得 \(n\) 在 \(b\) 進制下的數位和爲 \(s\) 。
\(n,s \le {10}^{11}\)
對於 \(< \sqrt n\) 的 \(b\) 咱們能夠暴力枚舉,而後逐位拆解求和,複雜度是 \(O(\sqrt n \log n)\) 的。
對於 \([\lceil \sqrt n \rceil, n]\) 的 \(b\) ,那麼 \(n\) 在 \(b\) 進制下只有兩位,其實就是解一個以下的方程:
\[ \begin{align} \lfloor \frac{n}{b} \rfloor + n \bmod b &= s \\ \lfloor \frac{n}{b} \rfloor + (n - \lfloor \frac{n}{b} \rfloor \times b) &= s\\ \lfloor \frac{n}{b} \rfloor (1 - b) &= s - n \\ b &= \frac{n - S}{\lfloor \frac{n}{b} \rfloor} - 1 \end{align} \]
不難發現 \(\displaystyle \lfloor \frac{n}{b} \rfloor\) 只有 \(\sqrt n\) 種取值,咱們直接整除分塊,而後解方程便可。
而後對於 \(n = s\) 的點須要特判,\(b\) 此時爲 \(n + 1\) 。
因此最後複雜度是 \(O(\sqrt n \log n)\) 的。
對於進制下的題,要麼數位 \(dp\) ,要麼考慮分狀況討論。
\(\ge \lceil \sqrt n \rceil\) 的進制只會有兩位,\(< \lceil \sqrt n \rceil\) 的進制位也只有 \(\log n\) 層。
戳這裏。
定義一個內部不包含循環子串 \(S\) 至少出現兩次的串爲好串,好比 \(\underline{a}\) 爲好串,\(\underline{abab}\) 不爲好串,\(\underline{cdcdc}\) 爲好串。
給你一個字符串 \(w\) ,如今要把它劃分紅不少段好串,其中段數要儘可能少。而後問段數儘可能上的前提下,問有多少種劃分方式。(對於 \(10^9 + 7\) 取模)
假設最好最優的段數爲 \(l\) 。
判斷一個串是否爲好串能夠先用 \(kmp\) ,求出每一個前綴的 \(fail\) (也就是這個前綴的最長公共先後綴 \((border)\) )
而後就能夠用一個經常使用性質了:
最小循環串(不必定會出現完畢)的長度等於 \(len - border\) ,具體證實能夠參考 這裏 。
而後它爲好串,當且僅當 \(fail_i\) 爲 \(0\) 或者 \(i \mod (fail_i - i) \not = 0\) 。前者由於最小循環串是本身自己,後者由於不能徹底填滿。
首先能夠特殊考慮兩種狀況:
剩下的狀況其實答案都爲 \(l = 2\) ,爲何呢?
由於你能夠考慮把 \(1 \sim |w| - 1\) 分到一組,最後一個字母單獨分紅一組。
若是這樣不可行的話,只有兩種狀況:
- 所有字母相等,前面會特判掉。
- \(1 \sim |S| - 1\) 存在一個最小循環串 \(|S|\) 至少出現兩次,和最後一個拼起來後必定使得整個串不存在一個可行的最小循環串。
而後剩下計算方案數,只須要枚舉斷點,而後判斷先後綴是否爲好串便可。( \(kmp\) 預處理兩次就好了)
牢記 \(border(fail)\) 與 最小循環串 互相轉化的性質。
戳 這裏 。
給你一顆有 \(n\) 個點的樹,一開始有 \(k\) 個點有權值。問是否能讓其餘的點也賦上權值,使得相鄰兩個節點的權值差的絕對值爲 \(1\) 。
若是能夠,請給出一組構造方案知足條件。
\(1 \le k \le n \le 10^5\)
首先分層考慮奇偶性是否存在解。
而後你對於每一個點維護它可取的權值範圍 \([l_i, r_i]\) 。
而後每次須要從兒子轉移上來:
\[ l_u = \max\{l_u, l_{son} - 1\}\\ r_u = \min\{r_u, r_{son} + 1\} \]
邊界就是,這個點無權值就是 \([- \infty, \infty]\) ,有權值就是 \([val_u, val_u]\) 。
若是 \(l_u > r_u\) 無解。
而後只須要從上往下隨意構造一組方案便可 。
樹上構造關於權值構造能夠考慮奇偶性。關於差值,能夠考慮每一個點的取值範圍而後向上轉移便可。
戳 這裏 。
平面上有 \(n\) 個點,其中選出兩個點 \(a, b\) ,令他們之間的曼哈頓距離爲 \(D\) 。
兩個點聯通當且僅當這兩個點之間的曼哈頓距離也爲 \(D\) ,最後詢問 \(a\) 所在聯通塊的每一個點的度數之和。
\(1 \le n \le 10^5\)
一道挺不錯的套路題。
看到曼哈頓距離不難想到能夠與切比雪夫距離進行轉換。
切比雪夫距離:
平面上兩點 \((x_1, y_1), (x_2, y_2)\) 之間的距離爲 \(\max(|x_1 - x_2|, |y_1 - y_2|)\) 。
如何轉換呢?考慮把原來座標系旋轉 \(45^{\circ}\) 。原來的座標 \((x, y)\) 就變成了 \((x + y, x - y)\) 。
而後原圖上兩點的曼哈頓距離就變成切比雪夫距離了。
來理性地證實一波:
假設原來兩點爲 \((x_1, y_1), (x_2, y_2)\) 變化後就是 \((x_1 + y_1, x_1 - y_1), (x_2 + y_2, x_2 - y_2)\) 。
\[ \begin{align} d_{\mathcal{Chebyshev}} &= \max{\{|(x_1+y_1) - (x_2 + y_2)|, |(x_1 - y_1) - (x_2 - y_2)|\}}\\ &=\max{\{|(x_1-x_2) + (y_1 - y_2)|, |(x_1 - x_2) - (y_1 - y_2)|\}}\\ &=\max{\{|(x_1-x_2) \pm (y_1 - y_2)|\}}\\ &=|x_1 - x_2| + |y_1- y_2| \end{align} \]
注意最後一步能夠本身討論兩邊的正負來證實。
而後轉了後,咱們就能夠轉化成對於兩個點其中一維的差值恰好爲 \(D\) ,另一維 \(\le D\) 。
爲了方便討論,咱們先假設 \(x\) 差值爲 \(D\) ,另外的一維也是同樣討論。
\[ \begin{cases} x_1 - x_2 = D\\ -D\le y_1 - y_2 \le D \end{cases} \]
咱們固定一維 \(x\) ,那麼另一維 \(y\) 就處於一個範圍內,咱們就能夠快速處理出一個點的度數爲多少了。
具體實現就是按 \(x\) 排序, \(x\) 相同按 \(y\) 排序,而後用兩個指針 \(l, r\) 維護當前的區間 \([l, r]\) 就好了。(由於區間是單調的)
可是連邊確定不能暴力連,但咱們發現是處於一段連續區間內,是否能夠線段樹優化建邊呢?是能夠的,但徹底沒有必要。
由於最後咱們只須要求聯通塊,只須要保證連通性不會變,那麼每次連邊的時候咱們發現相鄰的不須要重複連邊沒有意義,咱們每次記個 \(pos\) 表示當前連邊的區間掃到哪了就好了,而後這個點連向最後一個就好了。
這樣的話最後的邊數是 \(O(n)\) 的了,最後總複雜度是 \(O(n \log n)\) 的,瓶頸在排序上。
曼哈頓距離經常能和切比雪夫距離轉化,而後經常定下一維另一個就是個區間範圍,這樣就好處理不少了。
而後區間連通性連邊能夠用操做把邊數降到 \(O(n)\) 。
戳 這裏,挺短的。