P4213 【模板】杜教篩(Sum) 題解

博客園同步

原題鏈接

前置知識:

莫比烏斯反演,線性篩,狄利克雷卷積,整除分塊。

簡要題意:

TT 組詢問,求:

i=1nμi\sum_{i=1}^n \mu_i

i=1nϕi\sum_{i=1}^n \phi_i

其中,T10T \leq 10n<231n < 2^{31}.

首先,你需要知道這道題目的 O(Tnn)O(Tn \sqrt{n}) 算法,O(Tn)O(Tn) 算法,O(T+n)O(T+n) 算法。

顯然,O(Tnn)O(Tn \sqrt{n}) 是暴力,O(Tn)O(Tn) 是一個個篩,O(T+n)O(T+n) 是預處理 線性篩,一個都無法通過。

這題的瓶頸在於,我們 並不需要一個個求出 μ\muϕ\phi,可以不拘泥於此

想想:我們之前求 i=1nni\sum_{i=1}^n \lfloor \frac{n}{i} \rfloor 的時候,之前手玩 莫比烏斯反演 的時候,甚至有一次玩到 66\sum 還是一一解決了。走過這麼多困難,切掉了這麼多紫題,這一題怎麼就不行了呢?

事實告訴人們,題目從來都是人做出來的。

我們考慮幾個簡單的卷積:

μI=ϵ,ϕI=Id,μId=ϕ\mu * \text{I} = ϵ , \phi * \text{I} = \text{Id} , \mu * \text{Id} = \phi

好,根據這些,我們開始了偉大的探索。

假設我們要求一個 積性函數 ff,可以先不直接求,搞出另一個 gg,首先考慮怎麼求出 fgf * g 的前綴和,那樣就可以求出 f\sum_f.

根據 莫比烏斯反演 的性質可得:

i=1n(fg)(i)\sum_{i=1}^n (f*g) (i)

=i=1ndif(d)×g(id) = \sum_{i=1}^n \sum_{d|i} f(d) \times g(\frac{i}{d})

=d=1ng(d)×i=1ndf(i) = \sum_{d=1}^n g(d) \times \sum_{i=1}^{\lfloor \frac{n}{d} \rfloor} f(i)

假設 ff 的前綴和爲 SS,則:

=d=1ng(d)S(nd) = \sum_{d=1}^n g(d) S(\lfloor \frac{n}{d} \rfloor)

現在我們要求的是 S(n)S(n).

g(1)S(n)=d=1ng(d)S(nd)d=2ng(d)S(nd)g(1) S(n) = \sum_{d=1}^n g(d) S(\lfloor \frac{n}{d} \rfloor) - \sum_{d=2}^n g(d) S(\lfloor \frac{n}{d} \rfloor)

顯然,因爲 g(1)S(n)g(1) S(n)d=1d=1 的答案,考慮前綴和相減即可。

此時可以得到:

g(1)S(n)=d=1n(fg)(d)d=2ng(d)S(nd)g(1) S(n) = \sum_{d=1}^n (f * g) (d) - \sum_{d=2}^n g(d) S(\lfloor \frac{n}{d} \rfloor)

那麼顯然:

S(n)=d=1n(fg)(d)d=2ng(d)S(nd)g(1)S(n) = \frac{\sum_{d=1}^n (f * g) (d) - \sum_{d=2}^n g(d) S(\lfloor \frac{n}{d} \rfloor)}{g(1)}

此時你會說了,好,這個式子怎麼求呢?

這個式子確實難求,但關鍵是,gg 函數是我們自己定的,我們可以定一個 gg 使得 ggfgf*g 的前綴和都非常好算

好算?聯繫積性函數的性質,我們想到了:I\text{I}ϵϵ 都是積性函數,前綴和也非常的簡單。後面一堆我們可以整除分塊。

先不管怎麼定 gg,僞代碼大概長這樣:

inline ll sieve(ll n) {
	ll ans=calc(n); //calc(i) 負責計算 (f*g)(i)
	for(ll i=2,r;i<=n;i=r+1) {
		r=(n/(n/i));
		ans-=(sum(r) - sum(i-1)) * sieve(n/i); //sum(i) 計算 g 的前綴和
	} return ans;
}

顯然你會發現,這裏有遞歸部分。

遞歸?這東西,顯然會把很多東西重複計算。

因此我們需要 記憶化

到這裏,杜教篩 的樣子漸成,我們已經得到了其中的 60%60 \%.

下面的難點在於確定 gg.

入手題目。

f=ϕf = \phi,令 g=Ig = \text{I},則 fg=Idf * g = \text{Id},此時可以解決。

f=μf = \mu,令 g=Ig = \text{I},則 fg=ϵf * g = ϵ,此時也可以解決。

好了,現在的問題在於,這東西的時間複雜度如何?

你發現無法通過,因爲,杜教篩必須要初始化一部分數據

假設我們將 nkn \leq k 的情況的答案都初始化一遍。那麼,經過分析(具體證明) 可得,這樣的時間複雜度是:

O(k+nk)O(k + \frac{n}{\sqrt{k}})

你會發現,只要 O(k)O(k) 不出問題,kk 越大越好。

顯然,kknk\frac{n}{\sqrt{k}} 成反比,相等時和最小。(反比例函數知識)

所以,k=n23k=n^{\frac{2}{3}} 時,時間複雜度達到 O(n23)O(n^{\frac{2}{3}}),是比較優的。

時間複雜度: O(Tn23)O(Tn^{\frac{2}{3}}).

實際得分:100pts100pts.

博主的代碼太醜,不想拿出來了。以後會重構代碼發出來的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章