min_25 篩是由 min_25 大佬使用后普遍推廣的一種新型算法,這個算法能在 \(O({n^{3\over 4}\over log~ n})\) 的復雜度內解決所有的積性函數前綴和求解問題(個人感覺套上素數定理證明的復雜度的話應該要把下面的 log 改成 ln ,不過也差不多啦~)
其實 min_25 篩的入門TXC 大佬的 blog 已經寫的非常棒了QVQ
所以搬博客的話鑒於博主太懶了就不干了...直接幫 TXC 大佬安利博客完事
這篇博客主要的目的是證明網上大多沒有的 min_25 篩的復雜度
所以你首先得學會 min_25 篩...
前置芝士
Min_25 篩
素數定理
proof
首先我們知道 min_25 篩做了兩件事:
-
篩出一個所求函數的質數前綴和
-
遞歸/循環 得到所求函數的前綴和
對於第一個部分和第二個部分我們發現都有一個枚舉質數的過程,那么我們需要先知道 n 范圍內的質數個數
這就需要素數定理了,素數定理指:在 n 以內的素數個數是 \(O({n\over ln~ n})\) 的(下面為了方便起見就用 \(log ~n\) 代替這里的 \(ln~n\) 了 )
至於具體證明就不是本博客的任務了 QVQ
我們可以根據這一點結合埃氏篩法的復雜度得知:
我們在進行 min_25 中處理的 \(2\sqrt n\) 個數的函數前綴和時,一個數 x 被篩到過 \(O({\sqrt x\over log~ \sqrt x})\) 次
並且,無論是篩出所求函數關於 x 的質數前綴和還是全部的前綴和,都是這個次數(如果你寫過循環代替遞歸版的 min_25 的話,就更加清楚這是為什么了)
這里可以貼出我寫的一種 min_25 篩的版本(以篩 mu 的前綴和為例):
inline int ID(Rg int x){
return x<=sq?id1[x]:id2[n/x];
}
inline int calc(Rg int k,int j){
return w[k]>=p[j]?h[k]-j+1:0;
}
inline void Min_25(ll n){
sq=sqrt(n),m=0; int tot=0;
for(tot=1;1ll*p[tot]*p[tot]<=n;++tot);
for(Rg ll l=1;l<=n;l=w[m]+1){
w[++m]=n/(n/l),
h[m]=w[m]-1,Mu[m]=0,
//這里的 h 指質數個數的前綴和 , Mu 指莫比烏斯函數的前綴和
if(w[m]<=sq) id1[w[m]]=m;
else id2[w[m]]=m;
}
for(Rg int j=1;j<=tot;++j){
for(Rg int i=m;i&&1ll*p[j]*p[j]<=w[i];--i)
h[i]-=h[ID(w[i]/p[j])]-j+1;
}
for(Rg int j=tot;j;--j){
for(Rg int i=m,k;i&&1ll*p[j]*p[j]<=w[i];--i)
Mu[i]-=Mu[k]-calc(k,j+1);
}
for(Rg int i=m;i;--i) Mu[i]-=h[i];
}
不壓行真的好難受嚶嚶嚶...
我們發現上面篩出 mu 前綴和的時候兩個處理部分都是用了極其類似的雙重循環,(並且保證了答案是對的...),那么也就可以證明上面的說法了
所以我們就可以列出復雜度的式子:
主定理一波就是:
然后開始積分:
然后正常做法就難搞了,那么我們假一點,反正求的是大致復雜度,那么我們讓下面的表達式直接變為 \(log~ n\)(這里把常數直接略去) 這樣我們的任務就只剩下求上面表達式的積分了
至於這樣為什么可行? 我們發現下面的表達式中有一個 log ,雖然我們讓下面的表達式都變大了,但在 log 后,不過是少個常數的問題
如果這里有疑問的話,我們也可以把下面的表達式改成最小的 \(log~\sqrt{n}={1\over2}log~\sqrt{n}\),然后我們再把 \(1\over 2\) 忽略,這樣的結果和上面是一樣的...
於是乎原來的式子就變成了:
上面的那個積分已經是個多項式了:
這樣整個 min_25 篩的復雜度就證明完畢啦~