1. 程式人生 > >【總結】積性函式字首和(杜教篩)

【總結】積性函式字首和(杜教篩)

前言:

據CCH和LJH說,杜教篩似乎是一個非常套路的東西,幾乎所有的杜教篩的題目推理方式都是一模一樣的(但實測有些推理還是很噁心的)。所以複習杜教篩不需要太多時間,粗略看一遍,留下印象即可。

杜教篩其實是一種簡化運算的推理方式,它的使用條件並不僅限於積性函式(?),只是積性函式可以將複雜度進一步優化。

例題:求尤拉函式字首和

因為杜教篩是一種推理方式,所以直接給出例題反而容易上手。
尤拉函式的定義這裡就不再贅述。
需要知道的是尤拉函式(φ)的一個特殊性質:

d|nφ(d)=n
形如d|nf(d)=A這個性質是極為重要的,我們整個演算法都是基於這個性質而來。

下面開始推導:

φ(n)=nd|n,d<nφ(d)
那麼
i=1inφ(i)=i=1in(id|i,d<iφ(d))
現在我們改變列舉變數:我們列舉id的值,即列舉i對d的倍數,因為i≠d,所以從2開始
i=1inφ(i)=n(n+1)2id=2idnd=1dnidφ(d)
這時候就能夠驚訝地發現:
如果設Sum(n)=i=1inφ(i)
那麼就可以寫為:
Sum(n)=n(n+1)2id=2idnSum(nid)
我們成功地將問題化簡了!為了方便起見,我們將這個id寫為i
Sum(n)=n(n+1)2i=2inSum(ni)
接下來,只需要按照根據ni的不同取值來分塊,就可以達到O(n34)的複雜度。
顯然這還不夠優秀,那麼針對與積性函式,我們還有一個小優化: