1. 程式人生 > 實用技巧 >杜教篩

杜教篩

前置知識:熟悉 狄利克雷卷積

這個東西是用來快速求出積性函式的某個字首和,時間複雜度大概是 \(O(n^{\frac{2}{3}})\)

假定要求的是 \(\sum_{i=1}^{n}f(i)\) ,現在要找到另一個積性函式 \(g\) 把它們捲起來,得到 \(h=f*g\)

然後就是一大波變式。

\(S(n) = \sum_{i=1}^{n}f(i)\)

\[\begin{aligned} \sum_{i=1}^{n}h(i) &= \sum_{i=1}^{n} \sum_{d|i} f(d) \times g(\frac{i}{d}) \\ &= \sum_{i=1}^{n} \sum_{d|i} g(d) \times f(\frac{i}{d}) \\ &= \sum_{d=1}^{n} \sum_{i=1}^{\lfloor \frac{n}{d} \rfloor}g(d) \times f(i) \\ &= \sum_{d=1}^{n}g(d) \sum_{i=1}^{\lfloor \frac{n}{d} \rfloor}f(i) \\ &= \sum_{d=1}^{n}g(d) S(\lfloor \frac{n}{d} \rfloor) \end{aligned}\]

\(d=1\) 時,\(\lfloor \frac{n}{d} \rfloor=n\) ,正好是要求的,所以把它單獨分出來。

\[\sum_{i=1}^{n}h(i) = g(1)S(n) + \sum_{d=2}^{n}g(d) S(\lfloor \frac{n}{d} \rfloor) \]

\[g(1)S(n) = \sum_{i=1}^{n}h(i) - \sum_{d=2}^{n}g(d) S(\lfloor \frac{n}{d} \rfloor) \]

如果能快速求出右邊式子的值,就知道 \(S(n)\) 了。

所以要找到合適的 \(g\) ,使得 \(h\)\(g\)

的函式值能快速得到。

先假定上式的 \(h\)\(g\) 的值能 \(O(1)\) 算出。

負號右邊用整除分塊求值,但是 \(\lfloor \frac{n}{d} \rfloor\) 最大才縮小了一半,還是不能直接求,所以遞迴求解。

應用