1. 程式人生 > 其它 >AtCoder 記錄

AtCoder 記錄

總覽

為什麼你們都有腦子

\(\color{red}\bigodot\) | AGC006

\(f(i)\) 表示點 \(i\) 的期望座標,容易得到轉移 \(f(i)\gets f(i-1)+f(i+1)-f(i)\)

轉移很複雜,考慮差分,設 \(d(i)=f(i)-f(i-1)\),則轉移之後

\[\begin{aligned}d(i)&\gets(f(i-1)+f(i+1)-f(i))-f(i-1)=f(i+1)-f(i) \\ d(i+1)&\gets f(i+1)-(f(i-1)+f(i+1)-f(i))=f(i)-f(i-1)\end{aligned} \]

發現轉移一次等價於交換 \(d(i)\)

\(d(i+1)\),則轉移 \(m\) 次之後相當於一個置換。可以直接對置換做快速冪。但也可以把置換內部若干環提出來,則該環內的點做 \(K\) 次置換相當於做 \(K \bmod \mathrm{size}\) 次,則可以做到線性。

考慮二分,設 \(b_i = [a_i \ge \mathrm{mid}]\),手玩一下可以發現,假如 \(b\) 中存在一段離第 \(n\) 位最近的 \(00\),此時 \(b\) 序列相當於 \(\cdots \color{red}00\color{black}101\cdots101\color{red}00\color{black}\cdots\)

,每次這個 \(00\) 都會向中間拓展一位,則最後頂上的數只和離中間最近的一段 \(00\)\(11\) 有關。

\(\color{red}\bigodot\) | AGC009

考慮樸素的 DP,設 \(f(i)\) 表示第一個集合最後一個數是 \(a_i\) 的方案數。

考慮 \(j\) 要轉移到 \(i\) 需要滿足:

  1. \(j < i\)
  2. \(a_i-a_j \ge A\)
  3. \(\forall x,y \in [j+1,i-1],|a_x-a_y| \ge B\)

然而這樣轉移是錯的,若 \(a_{j+1}-a_{j-1} < B\)

就會有問題。

但是如果欽定 \(A \ge B\),易證存在這種情況則該序列一定無解。所以特判掉即可。

\(\color{red}\bigodot\) | AGC028

相當於在 \(2n\)\(a,b\) 中選 \(n\)\(a,b\)。設選擇的集合為 \(S\),則每個點被選的情況有四種:\(00,01,10,11\)

如果全是 \(01\) 或 全是 \(10\),就把它們全部接起來就行。

如果既有 \(01\) 又有 \(10\),容易證明 \(00\)\(11\) 的個數一定相等。如果有 \(00,11\),在 \(01\)\(10\) 中間塞即可,否則一定不合法。

上面是構造方案合法的必要條件。但實際上我們只用考慮這個條件,因為如果沒有選 \(\min\),顯然選了 \(\min\) 的方案也會被這個條件判為合法,即沒選 \(\min\) 不會產生貢獻。

考慮最優解為什麼。先對 \(2n\)\(a,b\) 排序得到 \(p_1,p_2,\cdots,p_{2n}\),選 \(p_1,p_2,\cdots,p_n\),如果不合法就選 \(p_1,p_2,\cdots,p_{n-1},p_{n+1}\),如果還不合法,則 \(p_n,p_{n+1}\) 一定是某個點 \(u\) 的一對 \((a_u,b_u)\)。強制同時不選 \(p_n,p_{n+1}\)(即 \(00\))或強制同時選 \(p_n,p_{n+1}\)(即 \(11\))都是合法的,取其中的最小值即可。

\(\color{red}\bigodot\) | AGC043

\(n=1\) 則直接輸出,否則差分一次之後原序列值域就變成了 \(\{0,1,2\}\)。那我們先差分一次,並且令 \(n \gets n-1\)

若序列中有 \(1\),則答案一定不為 \(2\)。此時 \(x_{i,j}=|x_{i-1,j}-x_{i-1,j+1}| \Longleftrightarrow x_{i,j}=(x_{i-1.j}+x_{i-1,j+1})\bmod 2\)。則 \(x_{n,1}=\left(\sum_{i=1}^n \binom{n-1}{i-1}x_{1,i}\right) \bmod 2\)。若序列中沒有 \(1\),則先把整個序列除以 \(2\),就和前面一樣,最後再乘 \(2\) 即可。

有一個結論:\(\dbinom n m \bmod 2 = [n \land m = m]\),具體證明可以考慮質因子 \(2\) 的次數,也可以考慮 Lucas 定理。

\(\color{red}\bigodot\) | AGC044

考慮平移操作,每次相當於令最低位 \(0\to 1,1\to 2,2\to 0\),並且最低位是 \(2\) 的數繼續考慮次低位的變換。則把所有數倒著插入到 Trie 上,平移操作就相當於是在 Trie 上的一條鏈跑。至於 \(1,2\) 互換操作就是打一個翻轉標記。

一個看不懂的 DP 做法

\(\color{orange}\bigodot\) | ARC059

考慮用 \(n\) 部構造出的字串 \(s\),字串的個數有 \(2^{|s|}\) 個。

\(f(i,j)\) 表示 \(i\) 步構造出長度為 \(j\) 的字串的方案數,顯然有

\(f(i+1,j+1) \gets f(i+1,j+1)+2f(i,j)\)

\(f(i+1,\max\{0,j-1\}) \gets f(i+1,\max\{0,j-1\}) + f(i,j)\)

則答案為 \(\dfrac{f(n,|s|)}{2^{|s|}}\)

\(\color{orange}\bigodot\) | ARC063

用 DP 求出每個點可選數的區間即可。

顯然有 \(ans \ge 2\times \max\{W,H\}+2\),則容易證明最有矩形一定經過 \(y=\dfrac H 2\)\(x=\dfrac W 2\)

\(\color{orange}\bigodot\) | ARC066

考慮 \(a+b=(a\oplus b)+2(a \land b)\),容易發現每個合法 \((u,v)\) 都對應唯一的 \((a,b)\)

顯然 \(u \le v\),則只需要令 \(v\le n\) 即可。

\(f(i)\) 表示滿足 \(v \le i\)\((u,v)\) 的方案數。

考慮這個時候對 \(f(i)\) 對應的所有數增加一個最低位。

由上得最低位只有三種情況:\((0,0),(0,1),(1,1)\)

若為 \((0,0)\),則 \(i'=2i\)

若為 \((0,1)\),則 \(i'=2i+1\)

若為 \((1,1)\),則 \(i'=2i+2\)

\(f(i)=f\left(\left\lfloor \frac i 2\right\rfloor\right)+f\left(\left\lfloor \frac {i-1} 2\right\rfloor\right)+f\left(\left\lfloor \frac{i-2} 2\right\rfloor\right)\)

可以發現每個 \(i\) 只會轉移到兩個狀態 \(k,k-1\)。手玩一下可以發現再遞迴下去還是兩個數,則總時間複雜度為 \(O(\log n)\)

顯然括號只會加到 \(-\) 號後面,一個括號內的形式是 \((++\cdots++-\cdots)\),則 \(+\) 號的都會變成負數,而內部第一個 \(-\) 號開始的所有數都可以通過加括號變成正數。直接列舉最外層括號位置即可。

\(\color{orange}\bigodot\) | ARC074

只用考慮每種顏色第一次出現的位置。設 \(f(i,j,k)\) 表示考慮到 \(a_i,a_{i+1},\cdots,a_n\),其中 \(a_j\) 是第一個 \(\neq a_i\) 的,\(a_k\) 是第一個 \(\neq a_i\)\(\neq a_j\) 的,直接轉移即可。

\(\color{orange}\bigodot\) | ARC082

題解

\(f_A(t)\) 表示起點為 \(A\),到了時間 \(t\) 時的沙子數,容易用 \(O(t)\) 的時間遞推求出。

畫出 \(f_0\)\(f_X\) 的影象,容易發現任意 \(A\in[0,X]\)\(f_A\) 都夾在 \(f_0\)\(f_X\) 的中間。

可以預處理出 \(f_0,f_X\),設 \(s_A(t)\) 表示不考慮上下界時,起點為 \(A\),到達時間 \(t\) 的沙子數。容易證明,如果有一個時刻 \(t'\in[0,t]\) 滿足 \(s_A(t') < 0\)\(s_A(t') > X\),則一定有 \(s_A(t)<f_0(t)\)\(s_A(t)>f_X(t)\)。否則全過程並沒有越過上下界,答案即為 \(s_A(t)\)

實際實現只需要預處理出 \(s_0\),容易得到 \(s_A(t)=s_0(t)+A\)

故答案為 \(\min\{f_X(t),\max\{f_0(t),s_A(t)\}\}\)

\(\color{orange}\bigodot\) | ARC083

題解

\(\color{orange}\bigodot\) | ARC084

考慮一個數 \(u\) 的各位和是 \(\mathrm{sum}(u)\)\(u\) 可以轉移到 \(10u\),貢獻是 \(\mathrm{sum}(u)\)\(u\) 也可以轉移到 \(u+1\),貢獻是 \(\mathrm{sum}(u)+1\)。對 \(u \bmod K\) 跑 01-BFS 即可

\(\color{orange}\bigodot\) | ARC089

題解

\(\color{orange}\bigodot\) | ARC092

考慮 \(u \to v\) 變成 \(v \to u\) 會產生影響的條件是什麼。

  1. \(u,v\) 在同一個強連通分量中:
    若存在 \(u \rightsquigarrow v\) 不經過 \(u \to v\),則該強連通分量不會被破壞;否則會被破壞。

  2. \(u,v\) 不在同一個強連通分量中:
    若存在 \(u \rightsquigarrow v\) 不經過 \(u \to v\),則不會產生影響;否則它們會連成一個新的強連通分量。

可以跑一次 Tarjan 判斷是否在同一個強連通分量。

當然你會發現 \(u,v\) 在同一個強連通分量的充要條件是存在 \(v \rightsquigarrow u\),則跑 \(n\) 次 DFS 求出任意兩點能不能到達也可以。

關鍵是如何判斷是否存在 \(u \rightsquigarrow v\) 不經過 \(u \to v\),這個問題等價於 \(u \to v\) 是否是 \(u \rightsquigarrow v\) 的必經邊。

考慮刪除 \(u\) 以及與其相關的邊,對於 \(u\) 原先指向的點 \(v_1,v_2,\cdots,v_k\),按順序從 \(v_1\)\(v_k\),跑 \(k\) 次 DFS 標記每個點最先可以被哪個 \(v_i\) 經過。然後再把 \(u\) 出邊順序反過來,從 \(v_k\)\(v_1\),跑 \(k\) 次 DFS 標記每個點最先被哪個 \(v_i\) 經過。

對於 \(u \to v\),若 \(v\) 兩次被標記的結果一樣(或者說 \(v\) 在兩次 DFS 樹上深度都是 \(1\)),則 \(u \to v\)\(u \rightsquigarrow v\) 的必經邊。

預處理出來後隨便判斷一下就好。時間複雜度為 \(O(nm)\)

當然也可以更快。

考慮複雜度帶上 \(m\) 的原因是上面求必經點的 DFS 中,每個點即使被標記了,也可能再被若干條邊列舉到。

\(S_u\) 表示刪去 \(u\) 後,當前還沒被標記的點的集合,設 \(G_x\) 表示 \(x\) 的出點集合。把上面的對 \(v_i\) 跑 DFS 改成跑 BFS,則每次只需要列舉 \(S_u \cap G_x\) 即可。

把它們放到 bitset 上,可以用下面的程式碼快速求出每個 \(1\) 的位置。

for (int i = T._Find_first(); i != T.size(); i = T._Find_next(i))

時間複雜度為 \(O\left(\dfrac{n^3}w+m\right)\)

\(\color{orange}\bigodot\) | ARC103

\(u\)\(v\) 的父親,\(d(u) = d(v) + 2\mathrm{size}_u- n\)。顯然按 \(d_i\) 排序後最小的是重心,最大的是葉子。從大到小排序後列舉每一位,第一位一定是葉子所以 \(\mathrm{size}=1\),則父親的 \(d\) 也是確定的,直接二分即可。又因為按照這個順序構造,列舉到每一位的時候,該位置的 \(\mathrm{size}\) 都已經被確定,所以構造方案是唯一的。然而這樣做只是保證 \(\Delta d\) 合法,還要跑一次換根 DP 判斷 \(d\) 是否合法。

\(\color{orange}\bigodot\) | ARC107

\(f(i,j)\)\(i\) 個數拼出 \(j\) 的方案數。

如果第 \(i\) 個數選 \(1\),顯然方案數為 \(f(i-1,j-1)\)

如果第 \(i\) 個數不選 \(1\),則可以選 \(\dfrac 1 2,\dfrac 1 4,\cdots\)。考慮全部 \(\times 2\),則變成可以選 \(1,\dfrac 1 2,\cdots\)。顯然方案數為 \(f(i,2j)\)

則有轉移 \(f(i,j) = f(i-1,j-1)+f(i,2j)\)

因為 \(f(i,2j)\) 存在僅當 \(i \ge 2j\),所以 \(j\) 最多隻需要列舉到 \(i\)

答案為 \(f(n,m)\),複雜度為 \(O(n^2)\)

\(\color{orange}\bigodot\) | ARC111

\(i\) 連線點 \(a_i\) 和點 \(b_i\),原問題變成每次選一條邊的一個端點,最多能選多少個點。

如果是一棵樹,則可以選 \(n-1\) 個點。如果是一張圖,則選出一個生成樹,肯定存在一個點被非樹邊覆蓋,所以可以選 \(n\) 個點。

\(\color{orange}\bigodot\) | ARC115

考慮圖為一棵樹,如果 \(k\) 為奇數,則答案為 \(0\);如果 \(k\) 為偶數,則答案為 \(\dbinom n k\)

證明:如果 \(n = 1\),則顯然成立。如果 \(n>1\),則考慮選一個葉結點,然後選擇是否選葉結點連線的邊。如果不選這條邊,則原問題變成 \(n-1\) 個點裡要求 \(k\) 個點為奇點。如果選這條邊,則原問題變成 \(n-1\) 個點裡要求 \(k-2\) 個點為奇點,一直推下去即可。

然而可能圖不連通,所以要分別 DP 然後乘起來。

離散化之後能選的數分成 \(m\) 段。設 \(f(i,j)\) 表示選前 \(i\) 個數,第 \(i\) 個數放在第 \(j\) 段的方案數。

顯然有 \(f(i,j) = \sum\limits_{k=1}^{m} f(i-1,k) - f(i - 1,j)\),轉移是 \(O(n^2)\) 的。

建一棵線段樹,先整體 \(\times -1\),再整體加值,第 \(j\)\(+ len_j \times \sum\limits_{k=1}^m f(i-1,k)\),其中 \(len_j\) 表示第 \(j\) 段對應的數的數量。最後區間 \(\times 0\) 即可。

\(\color{orange}\bigodot\) | ARC116

分別考慮 \(a_n=1,2,\cdots,m\) 的情況,設 \(a_n = \prod\limits_{i=1}^tp_i^{c_i}\),則方案數為 \(\prod\limits_{i=1}^t\dbinom{n+c_i-1}{c_i}\)

顯然這是一個積性函式,把 \(\dbinom{n+c_i-1}n\) 拆成 \(\prod\limits_{j=1}^{c_i}\dfrac{n+j-1}{j}\),然後做線性篩即可。

考慮到 \(\bigoplus\limits_{i=1}^n a_i = 0\),則拆位之後,每一位只有偶數個 \(a_i\)\(1\)

\(f(i)\) 表示 \(\sum\limits_{j=1}^n a_j=i\) 的方案數,則有

\[f(i)=\begin{cases}\sum\limits_j\dbinom n {2j} f\left(\dfrac{i-2j}2\right)& i \bmod 2 =0\\0 & i \bmod 2=1\end{cases} \]

答案為 \(f(m)\)

\(\color{orange}\bigodot\) | ARC121

如果只能每次選兩個,顯然是排序後選 \((1,n),(2,n-1),\cdots\)

只選一個可以看作把它和 \(0\) 配對,則可以在原序列塞若干個 \(0\) 使得序列長度為偶數,然後每次選兩個。列舉加幾個 \(0\) 即可。

\(\color{orange}\bigodot\) | ARC123

\(\color{orange}\bigodot\) | ARC124

考慮到 \(x,y\) 一定分別是 \(a_1,b_1\) 的因數。

那我們可以列舉 \(x,y\),然後判斷是否滿足必要條件:\(x|a_i,y|b_i\)\(x|b_i,y|a_i\)

顯然對於不滿足充分條件的 \(x,y\)\(\operatorname{lcm}(x,y)\) 一定不為最優。

時間複雜度為 \(O(n\sqrt{a_1b_1})\)

\(\color{blue}\bigodot\) | ABC214

可以發現同一個強連通分量內的點,只要遍歷了一個就可以遍歷全部,所以先縮點。容易發現縮點後就是一個費用流板子,在 DAG 上 DP 求出初始勢能之後跑 Primal-Dual 即可。

\(\color{blue}\bigodot\) | ABC218

先跑一次 BFS 求出一條最短路,如果被刪的邊不在這條最短路上,則對答案沒有影響。如果在這條最短路上,就暴力跑一次 BFS 即可。時間複雜度為 \(O(nm)\)

顯然可以顛倒顏色使得 \(R \gets \min\{R, n - R\}\),容易證明可以轉化成選 \(R\) 個不相鄰的點,如果選了位置 \(i\),則貢獻為 \(a_{i-1}+a_i\)

容易發現這是一個凸函式,直接 WQS 二分即可。

貌似也可以分治。具體見官方題解

\(\color{blue}\bigodot\) | ABC219

設做一次 \(s\) 的移動順序為 \((x_0=0,y_0=0) \to (x_1,y_1)\to\cdots\to(x_n,y_n)\),又設 \(A=x_n,B=y_n\),則第 \(k\)\(s\) 的移動順序相當於 \((x_0+A,y_0+B)\to(x_1+A,y_1+B)\to\cdots\to(x_n+A,y_n+B)\)

考慮 \((x_0,y_0),(x_1,y_1),\cdots,(x_{n-1},y_{n-1})\) 分別的貢獻。設 \(t_i\) 為最小的 \(k\),使得 \(\exists j \neq i,(x_i+kA,y_i+kB)=(x_j,y_j)\)。可以發現對於 \((x_i,y_i)\),做前 \(k\)\(s\) 時都有貢獻,從第 \(t_i+1\)\(s\) 開始就一定沒有貢獻。則答案為 \(\sum_{i=0}^n \min\{t_i,K+[i = 0]\}\)

對於 \(t_i\),把每一個 \((x_i,y_i)\) 按照 \((x_i \bmod A,y_i \bmod A)\) 分類,丟到對應的 set 裡,每次在 set 裡找即可。

\(\color{blue}\bigodot\) | ABC225

考慮 \(k=n\) 的時候,就是對所有的 \(s_i\),按照 \(\forall i<j,s_i+s_j<s_j+s_i\) 排序。

傳遞性:

考慮把 \(s_i,s_j\) 看作 \(26\) 進位制數 \(a,b\),則 \(s_i<s_j \Longleftrightarrow a\times 26^{|s_j|}+b < b \times 26^{|s_i|} + a \Longleftrightarrow \dfrac a {26^{|s_i|}-1} < \dfrac b {26^{|s_j|}-1}\)

可以發現這個不等式只和自己有關,容易證明其傳遞性。

然後倒過來 DP,設 \(f(i,j)\) 表示 \(s_i,s_{i+1},\cdots,s_n\) 中選 \(k\) 個的最小字串,容易證明這樣做一定可以得到 按照順序 選擇得到的最小字串。(可以證明正過來 DP 是錯的)

考慮是否能不按照這個順序得到更小字串,可以證明這是與前面的排序矛盾的,所以無需考慮。