1. 程式人生 > 其它 >[筆記] 杜教篩

[筆記] 杜教篩

杜教篩

用來在非線性時間內求積性函式字首和

設現在要求積性函式 \(f\) 的字首和, 設 \(\sum \limits_{i=1}^{n} f(i) = S(n)\)

再找一個積性函式 \(g\) ,則考慮它們的狄利克雷卷積的字首和

\[\sum\limits_{i=1}^{n}(f*g)(i) \] \[\begin{aligned} &= \sum\limits_{i=1}^{n} \sum \limits _{d|i} f(d)g(\frac{i}{d}) \\ &= \sum \limits _{d=1}^{n} g(d)\sum\limits _{i=1}^{\lfloor \frac{n}{d}\rfloor } f(i) \\ &= \sum \limits _{d=1}^{n} g(d) S(\lfloor \frac{n}{d} \rfloor) \end{aligned} \]

再考慮一個式子

\[g(1)S(n)=\sum \limits _{i=1}^{n} g(i) S(\lfloor \frac{n}{i} \rfloor) - \sum \limits _{i=2}^{n} g(i) S(\lfloor \frac{n}{i} \rfloor) \]

所以得到杜教篩的核心式子:

\[g(1)S(n)=\sum\limits_{i=1}^{n}(f*g)(i) - \sum \limits _{i=2}^{n} g(i) S(\lfloor \frac{n}{i} \rfloor) \]

找到一個合適的積性函式 \(g\) ,使得可以快速算出 \(\sum\limits_{i=1}^{n}(f*g)(i)\)

\(g\) 的字首和,便可以用數論分塊遞迴地求解。

inline int F_sum(int n){
	if(n <= 5e6) return f[n];
	int &sum = n <= m ? F[n] : F[m + ::n / n];
	if(sum) return sum; sum = FG_sum(n);
	for(int l(2), r; l <= n; l = r + 1)
		r = n / (n / l), sum -= (G_sum(r) - G_sum(l - 1)) * F_sum(n / l);
	return sum;
}

技巧

  • 記憶化:

    上面的求和過程中出現的都是 \(\lfloor \frac{n}{i} \rfloor\) 。開一個大小為兩倍 \(\sqrt n\) 的陣列 \(dp\) 記錄答案。

    \(x \leq \sqrt n\) ,返回 dp[x] ,否則返回 dp[sqrt n + n / x] 即可。

  • 杜教篩的重點是對於要求的 \(f\),找到 \((f*g)\),滿足 \(g,(f*g)\) 的字首和都很好求出,如果沒辦法背下常見的狄利克雷卷積結果,不妨直接列舉幾個情況試試,來兩例子:

    • \(f(n)=\mu(n)n^2,g(n)=n^2,(f*g)(n)=[n=1]\)
    • \(f(n)=\varphi(n)n^2,g(n)=n^2,(f*g)(n)=n^3\)

題單

DZY Loves Math IV

開始在想能不能把 i 和 j 分開

因為 \(n\le10^5,m\le10^9\),所以比較自然地想到列舉 \(n\) 去求解,然後開始考慮對某一個 \(n\) 怎麼處理。

因為 \(\varphi\) 函式的一些性質:\(n=\prod_{i=1}^qp_i^{c_i},\varphi(n)=\varphi(\prod_{i=1}^qp_i)\prod_{i=1}^qp_i^{c_i-1}\)

考慮先把 \(n\) 的質因數次數高於一次的部分都提出來,記為 \(x\),剩下的 \(\frac{n}{x}\) 記為 \(y\).

\[\begin{aligned} \sum_{i=1}^m\varphi(ni) &=x\sum_{i=1}^m\varphi(yi)\\ &=x\sum_{i=1}^m\varphi(\frac{y}{\gcd(y,i)})\varphi(i)\gcd(y,i)\\ &=x\sum_{i=1}^m\varphi(\frac{y}{\gcd(y,i)})\varphi(i)\sum_{j\mid gcd(y,i)}\varphi(j) \ (這裡用的是\ n=\sum_{i\mid n}\varphi(i))\\ &=x\sum_{i=1}^m \varphi(i) \sum_{j\mid \gcd(y,i)}\varphi(\frac{y}{j}) \ (由於\ y\ 的特殊性,y\ 與\ \gcd(y,i)\ 的因數互質,可以直接乘)\\ &=x\sum_{i=1}^m \varphi(i) \sum_{j\mid y,j\mid i}\varphi(\frac{y}{j}) \ (然後對列舉順序進行一個交換)\\ &=x\sum_{j\mid y}\varphi(\frac{y}{j})\sum_{i=1}^{\frac{m}{j}}\varphi(ji)\ (整理到此處於是可以遞迴) \end{aligned} \]

總之記憶化後,複雜度是對的.