1. 程式人生 > 其它 >八月做題筆記

八月做題筆記

記錄了做到的一些不錯的題,也有模板和知識點。


CF1548C

題意

\(q\) 個詢問,每次給定 \(x\),求 \(\sum\limits_{i=1}^N\dbinom{3i}{x}\)\(1\leq N\leq 10^6\)

做法一

\(f_{x,k}=\sum\limits_{i=0}^{N-1}\dbinom{3i+k}{x}\),則有

  • \(f_{x,0}+f_{x,1}+f_{x,2}=\dbinom{3N}{x+1}\)
  • \(f_{x,1}=f_{x,0}+f_{x-1,0}\)
  • \(f_{x,2}=f_{x,1}+f_{x-1,1}\)

遞推就能做了。

用到了上指標求和公式(好像叫什麼 Hockey Stick Identity(?):

\[\sum\limits_{0\le k\le n}\binom{k}{m}=\binom{n+1}{m+1} \]
做法二

\[\begin{aligned} \ f_x &= \sum\limits_{i=1}^N\dbinom{3i}{x}\\ &= \sum\limits_{i=1}^N\left(\dbinom{3i-3}{x}+3\dbinom{3i-3}{x-1}+3\dbinom{3i-3}{x-2}+\dbinom{3i-3}{x-3} \right)\\ &=f_x-\dbinom{3N}{x}+3f_{x-1}-3\dbinom{3N}{x-1}+3f_{x-2}-3\dbinom{3N}{x-2}+f_{x-3}-\dbinom{3N}{x-3}\\ &=f_x+3f_{x-1}+3f_{x-2}+f_{x-3}-\dbinom{3N+3}{x} \end{aligned} \]

\(x-3\)

替換成 \(x\) 就得到遞推式

\[f_x=\dbinom{3N+3}{x+3}-3f_{x+1}-3f_{x+2} \]

比方法一的簡潔些。


斐波那契數列通項公式

\[F_n=\dfrac{1}{\sqrt{5}}(\alpha^n-\beta^n) \]

其中 \(\alpha=\dfrac{1+\sqrt{5}}{2}, \beta=\dfrac{1-\sqrt{5}}{2}\)

可以擴域做,即把 \(a+b\sqrt{5},(a,b\in\mathbb{Q})\) 看作廣義的“複數”進行運算。


長鏈剖分

樹上 k 級祖先

各種做法花裡胡哨,這裡說下長剖的做法( \(O(n\log n)-O(1)\)

)。

預處理:

  1. 對樹進行長鏈剖分,記錄每個點所在鏈的頂點和深度

  2. 樹上倍增求出每個點的 \(2^n\) 級祖先

  3. 對於每條鏈,如果其長度為 \(len\),那麼在頂點處記錄頂點向上的 \(len\) 個祖先和向下的 \(len\) 個鏈上的兒子

  4. \(i\in[1, n]\) 求出在二進位制下的最高位 \(h_i\)

對於每次詢問 \(x\)\(k\) 級祖先:

  1. 利用倍增陣列先將 \(x\) 跳到 \(x\)\(2^{h_k}\) 級祖先,設剩下還有 \(k^{\prime}\) 級,顯然 \(k^{\prime} < 2^{h_k}\),因此此時 \(x\) 所在的長鏈長度一定 \(\ge 2^{h_k} > k^{\prime}\)
  2. 由於長鏈長度 \(> k^{\prime}\),因此可以先將 \(x\) 跳到 \(x\) 所在鏈的頂點,若之後剩下的級數為正,則利用向上的陣列求出答案,否則利用向下的陣列求出答案。

(摘自https://www.luogu.com.cn/blog/xht37/solution-p5903

HOT-Hotels

經典問題,求樹上兩兩距離相等的三元組個數。

CCPC-Final 2019 G

題意

給定一棵 \(n\) 個節點樹,\(1\) 號節點有一個標記,兩個人輪流移動這個標記到另一個節點,每次移動的距離必須嚴格比上一次對手移動的距離長。求有多少個包含 \(1\) 節點的聯通子圖,使得這個遊戲後手必勝。

\(1\leq n\leq 2\times 10^5\)

做法

博弈就是紙老虎,不難看出,其實就是求有多少個子圖使得 \(1\) 節點是直徑中點。

先設計這個噁心的 dp。

\(f_{x,j}\) 表示以 \(x\) 為根且最大深度為 \(j\) 的子圖方案數。

轉移:

\[f_{x,j}=\left(\sum\limits_{k\leq j}f_{x,k}^{\prime}\right)\times f_{y,j-1}+f_{x,j}^{\prime}\times\sum\limits_{k<j}f_{y,k} \]

其中 \(y\in son(x)\)\(f^{\prime}\) 表示處理到當前兒子之前 \(f\) 的值,這是一個滾動的過程,下文的 \(g^{\prime}\) 同理。

考慮在 \(1\) 節點周圍統計答案,再設計一個更噁心的 dp。

  • \(g_{j,0}\) 表示以 \(1\) 為根且最大深度小於 \(j\) 的子圖方案;

  • \(g_{j,1}\) 表示以 \(1\) 為根且僅有一個兒子中的最大深度為 \(j\) 的子圖方案;

  • \(g_{j,2}\) 表示以 \(1\) 為根且有兩個或兩個以上兒子中的最大深度為 \(j\) 的子圖方案。

轉移:

\[g_{j,2}=g_{j,1}^{\prime}\times f_{y,j-1}+g_{j,2}^{\prime}\times \sum\limits_{k<j}f_{y,k}\\ g_{j,1}=g_{j,0}^{\prime}\times f_{y,j-1}+g_{j,1}\times \sum\limits_{k<j-1}f_{y,k}\\ g_{j,0}=g_{j,0}^{\prime}\times \sum\limits_{k<j-1}f_{y,k} \]

觀察這個轉移,我們發現所有轉移都和深度有關,於是想到用長剖優化。處理當前節點 \(x\) 時,繼承 \(x\) 重兒子的資訊,再列舉每個輕兒子所在長鏈,更新 \(x\) 的資訊。式子最後面的那個西格瑪,列舉 \(j\) 的時候維護一個字首和就好了。

不過還有一個問題,根據轉移,處理 \(x\) 時所有的 \(f_x\) 都會被輕兒子更新,但我們又不能列舉到 \(dep_x\)(否則複雜度有變成 \(n^2\) 了),不過再仔細觀察,我們發現當 \(j>dep_y\) 時,後面的那個西格瑪就是一個定值,這就相當於給 \(dep_y<j\leq dep_x\)\(f_{x,j}\) 都乘上一個定值,所以打個懶標記就好了,用到的時候再下傳懶標記,這樣就保證了總的複雜度 \(O(n)\)

\(g\) 的轉移也就同理了,打懶標記即可。

提交記錄


luogu P1273

\(O(n^2)\) 的樹上揹包

首先把所有節點按後續遍歷重新標號

\(f_{i,j}\) 為前 \(i\) 個點,揹包容量為 \(j\) 的最大價值。設 \(siz_i\) 為以 \(i\) 為跟的子樹大小。那麼 \(f_{i,j}\) 就會從 \(f_{i-1,j-1}\)\(f_{i-siz_i,j}\) 轉移過來。

loj 也有這個模板題 https://loj.ac/p/160