數論分塊之整除分塊
前言
最近在學莫比烏斯反演,然而只看懂了莫比烏斯函式,然後反演看著一臉懵逼,最後只看懂了數論分塊裡面的一個分支內容(也是莫比烏斯反演的前置姿勢),整除分塊
於是寫一篇博文記錄一下整除分塊
整除分塊
整除分塊是用於快速處理形似
\[ \sum_{i=1}^{n}{\lfloor \frac{n}{i} \rfloor} \]
的式子的方法
很顯然,這個可以\(O(n)\) 得到答案。但是,在某些題目中,毒瘤出題人將資料加強到了\(10^{10}\) 以上,這個時候我們就無法通過\(O(n)\) 的解法來得到答案了。我們需要一個\(O(\sqrt{n})\) 的更為優秀的解法
首先觀察這個式子,找幾個特殊值代入
n=5時,sum=5+2+1+1+1
可以發現的是:(這裡給的例子並不明顯,其實應該找一個大的n來代入才直觀,讀者可以自行嘗試)
對於單一的\(\lfloor \frac{n}{i} \rfloor\) ,某些地方的值是相同的,並且呈塊狀分佈
通過進一步的探求規律與推理
,我們可以驚喜的發現一個規律,這些塊狀分佈的值是有規律的
對於一個塊, 假設它的起始位置的下標為l,那麼可以得到的是,它的結束位置的下標為\(\lfloor \frac{n}{\lfloor \frac{n}{l}\rfloor} \rfloor\)
如果實在看的有點懵逼,可以繼續採用代入特殊值的方法,驗證一下上方的規律,用程式表現出來即為
//l為塊的左端點,r為塊的右端點 r=n/(n/l)
在實際應用中,需要注意的就是除法除0 的問題(一般都需要特判一下n/l)
程式實現也十分簡單
int ans = 0; for(int l = 1, r = 0; l <= n; l++) { r = n / (n / l); // do something }
實際應用
例題:ofollow,noindex" target="_blank">BZOJ1257: [CQOI2007]餘數之和
這題其實就是求
\[ \sum_{i=1}^{n}{k\space mod\space i} \]
這題和整除分塊又有什麼關係呢?
mod沒有什麼特殊的性質,所以我們將它展開來,就變成了
\[ \sum_{i=1}^{n}{k\space-\lfloor \frac{k}{i} \rfloor*i} \]
於是我們就看到了一個熟悉的形式,也就是整除分塊的一般形式
再次改一下這個式子
\[ n*k-\sum_{i=1}^{n}{\lfloor \frac{k}{i}\rfloor*i} \]
那麼
\(\sum_{i=1}^{n}{\lfloor \frac{k}{i}\rfloor*i}\)
和普通的整除分塊有什麼差別呢?
確實,就是多了一個i而已,只需要簡單的化簡一下,這個i就對我們的處理沒有什麼影響了
因為我們知道,對於一個整除分塊\(\sum_{i=l}^{r}{\lfloor\frac{k}{i}\rfloor}\) ,其中的每個值都是相同的,於是我們可以設\(T=\lfloor\frac{k}{i}\rfloor\)
式子就化為了
\[ \sum_{i=l}^{r}T*i \\ =T*\sum_{i=l}^{r}i \]
也就是說,其實這個式子前半段是一個整除分塊,後半段是一個首項為l,公差為1的等差數列
至此,我們就圓滿的解決了這個問題,可以在\(O(\sqrt{n})\) 的時間內解決本題
這是整除分塊中最基礎的應用,就是單純的利用整除分塊來加速遞推的實現,而實際上,整除分塊更多的與其他函式結合在一起來使用,優化問題的求解
整除分塊與積性函式
說到積性函式,就不得不講到兩個廣為人知的函式\(\phi,\mu\) ,這是我們最熟悉的積性函式
積性函式有一個很好用的性質(設\(f(i)\) 為一個積性函式):
\[ f(i*j)=f(i)*f(j) \]
這裡的\(f(i)\) 其實是一個完全積性函式。(\(\phi\) 就不是一個完全積性函式:\(\phi(i*j)=\phi(i)*\phi(j)\) 當且僅當i,j互質才成立)
好了,講完積性函式的這個性質後我們步入正題,整除分塊與積性函式的聯絡
很多時候,我們推出來整除分塊的式子不是很裸的,常與其他函式結合(通常是積性函式,通常為\(\mu\) 或\(\phi\) )
這個時候如何統計答案呢?
比如:
\[ \sum_{i=1}^{n}{\mu(i)*\lfloor \frac{n}{i}\rfloor} \]
積性函式的性質!
因為積性函式這個很好用的性質,所以我們可以直接對前半段的莫比烏斯函式維護一個字首和,再利用整除分塊處理式子的後半段,處理答案的時候,把兩段相乘即可
當然,整除分塊能結合的函式肯定不止這麼幾個
\(To\ Be\ Continue...\)