1. 程式人生 > 其它 >整除分塊(數論分塊)詳解

整除分塊(數論分塊)詳解

整除分塊(數論分塊)的詳細解釋和證明以及幾道練習題

整除分塊(數論分塊)

介紹

在求解問題

\[\sum_{i=1}^n\lfloor\frac ni\rfloor \]

時,若 \(n\) 的範圍很大那麼 \(\Theta(n)\) 求解將會超時,我們需要一種更高效的方法來計算,整除分塊就是這樣一種方法

不難發現,在 \(i\) 取某些值的時候 \(\lfloor\frac ni\rfloor\) 的值都是相同的,考慮將 \(\lfloor\frac ni\rfloor\) 的值相同的 \(i\) 一起計算,減少計算次數

那麼此時我們需要計算多少次呢?

\(i\le\sqrt n\) 時顯然 \(\lfloor\frac ni\rfloor\)

的取值只有 \(\sqrt n\) 種可能,而當 \(i>\sqrt n\) 時有 \(\frac ni<\sqrt n\) ,所以 \(\lfloor\frac ni\rfloor\) 的取值同樣只有 \(\sqrt n\) 種可能,也就是說 \(\lfloor\frac ni\rfloor\) 的取值只有 \(2\sqrt n\) 種可能,對於同樣的取值只用計算一次,總的時間複雜度也就是 \(\Theta(\sqrt n)\)

下面來說具體怎麼做

畫出 \(\lfloor\frac ni\rfloor\) 的影象不難發現,所有取值相同的 \(i\) 都是連續的整塊的,這也是這個演算法叫做整除分塊的原因,對於每一塊我們想要通過給出這一塊的左端點,\(\Theta(1)\)

計算出這一塊的右端點,這樣才能保證複雜度

假設現在我們的左端點是 \(l\),那麼設 \(\lfloor\frac nl\rfloor=k\),我們要求右端點也就是最大的 \(r=l+d\) 使得 \(\lfloor\frac n{l+d}\rfloor=\lfloor\frac nl\rfloor=k\)

\(\lfloor\frac nl\rfloor\)\(\lfloor\frac n{l+d}\rfloor\) 展開得 \(n=kl+p\)\(n=k(l+d)+p'\),其中 \(1\le p<l\)

那麼 \(kl+p=k(l+d)+p'\) 所以 \(p'=p-kd\)

,因為 \(p'\ge0\),所以 \(kd\le p\),所以 \(d\le\frac pk\),又因為 \(d\) 為整數,所以 \(d\) 最大能取 \(\lfloor\frac pk\rfloor\),其中 \(p=n\bmod l=n-l\lfloor\frac nl\rfloor\)\(k=\lfloor\frac nl\rfloor\)

所以我們有

\[\begin{align*} r&=l+d_\max\\ &=l+\lfloor\frac pk\rfloor\\ &=l+\lfloor\frac{n-l\lfloor\frac nl\rfloor}{\lfloor\frac nl\rfloor}\rfloor\\ &=l+\lfloor\frac n{\lfloor\frac nl\rfloor}-l\rfloor\\ &=\lfloor\frac n{\lfloor\frac nl\rfloor}\rfloor \end{align*} \]

也就是說,對於每一個左端點為 \(l\) 的塊,它的右端點為 \(\lfloor\frac n{\lfloor\frac nl\rfloor}\rfloor\)

\(\sum\limits_{i=1}^n\lfloor\frac ni\rfloor\) 我們從左端點 \(l\)\(1\) 開始列舉,每次右端點 \(r\)\(\min(n,\lfloor\frac n{\lfloor\frac nl\rfloor}\rfloor)\),將答案累加上 \((l-r+1)\lfloor\frac nl\rfloor\),然後令 \(l=r+1\) 不斷迴圈,當右端點等於 \(n\) 時停止迴圈

練習

練習一

Luogu P3935 Calculating

題目大意

給定 \(n\)\(\sum\limits_{i=1}^nd(i)\),其中 \(d(i)\) 表示 \(i\) 的約數個數

題解

\(1\)\(n\) 的約數顯然只能也在 \(1\)\(n\) 內,那麼考慮換一種方式表達 \(\sum\limits_{i=1}^nd(i)\),列舉 \(1\)\(n\) 的所有數,看列舉的數屬於多少個數的約數,假設當前列舉到數字 \(k\) 那麼在 \(1\)\(n\)\(k\) 屬於多少個數的約數,那麼也就是在問在 \(1\)\(n\)\(k\) 的倍數有多少個,顯然有 \(\lfloor\frac nk\rfloor\) 個,題目也就轉換為了求解 \(\sum\limits_{i=1}^n\lfloor\frac ni\rfloor\),整除分塊即可

練習二

P2261 [CQOI2007]餘數求和

題目大意

給定 \(n,k\),求 \(\sum\limits_{i=1}^nk\bmod i\)

題解

\(k\bmod i\) 可以寫作 \(k-i\lfloor\frac ki\rfloor\),原式即變為 \(\sum\limits_{i=1}^nk-i\lfloor\frac ki\rfloor=kn-\sum\limits_{i=1}^ni\lfloor\frac ki\rfloor\),考慮對於 \(\sum\limits_{i=1}^ni\lfloor\frac ki\rfloor\) 使用整除分塊,對於值相同的 \(\lfloor\frac ki\rfloor\),利用等差數列求和公式算出 \(i\) 的區間和,再乘以 \(\lfloor\frac ki\rfloor\) 就可以 \(\Theta(1)\) 累加進答案

再看整除分塊時 \(n,k\) 的上界問題,當 \(n\ge k\)\(i>k\) 的部分貢獻均為 \(0\),所以我們忽略 \(n\)\(k\) 大的部分,直接以 \(k\) 為上界計算 \(\sum\limits_{i=1}^k\lfloor\frac ki\rfloor\) 即可;當 \(n<k\) 時每次右端點變為 \(\min(n,\lfloor\frac k{\lfloor\frac kl\rfloor}\rfloor)\),右端點到 \(n\) 時停止


該文為本人原創,轉載請註明出處

部落格園傳送門