整除分塊(數論分塊)詳解
整除分塊(數論分塊)
介紹
在求解問題
\[\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\)
下面來說具體怎麼做
畫出 \(\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\)
所以我們有
\[\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\) 時停止迴圈
練習
練習一
題目大意
給定 \(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\),整除分塊即可
練習二
題目大意
給定 \(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\) 時停止
該文為本人原創,轉載請註明出處