1. 程式人生 > 其它 >整除分塊學習筆記

整除分塊學習筆記

前置知識

  • 莫比烏斯反演

上面的標題應該改為後置知識

前言

最近在嗑莫比烏斯函式時嗑到了這個知識點,本質上是一個經常與莫比烏斯反演一起出現的小技巧,包括在很多莫比烏斯反演的題目中。

演算法過程

整除分塊通常被用來處理類似下方的式子:

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

暴力

首先我們可以暴力解決:

int ans = 0;
for(int i = 1; i <= n; i++) {
	ans += n / i;
}
\[N \leq 10^9 \]

然後就歇菜了

規律

我們可以通過打表的方式來尋找\(\sum_{i=1}^n \lfloor \frac{n}{i} \rfloor\)

的規律

\(n=5,sum=5+2+1+1+1\)

\(n=9,sum=9+4+3+2+1+1+1+1+1\)

\(n=12,sum=12+6+4+3+2+2+1+1+1\)

可以看到有很多數是重複的,當\(n\)更大時,重複的數會更多。可以證明,這些數的數量是\(O(\sqrt{n})\)的。換句話說,我們可以將每一段連續且相同的數分開計算,實現\(O(\sqrt{n})\)的時間複雜度。

實現

可以證明,對於一段相同且連續的數,若其左端點為\(l\),則右端點為\(\lfloor \frac{n}{\lfloor \frac{n}{l} \rfloor} \rfloor\)

即這一段\(r-l+1\)

個數都為\(\lfloor \frac{n}{l} \rfloor\)\(l\)\(r\)的總和為\(\lfloor \frac{n}{l} \rfloor * (r - l + 1)\)

for(int l = 1, r; l <= n; l = r + 1) {
    r = n / (n / l);
    ans += (n / l) * (r - l + 1);
}

應用

「CQOI2007」餘數求和

這道題的關鍵是求\(\sum_{i=1}^n i * \lfloor \frac{n}{i} \rfloor\)

在此題中,\(l\)\(r\)的總和為\(\sum_{i=l}^{r} i * \lfloor \frac{n}{l} \rfloor = \lfloor \frac{n}{l} \rfloor \sum_{i=l}^{r} i = \lfloor \frac{n}{l} \rfloor * \frac{(l + r)(r - l + 1)}{2}\)

for(int l = 1, r; l <= n; l = r + 1) {
    r = n / (n / l);
    ans += (n / l) * (l + r) * (r - l + 1) / 2;
}

莫比烏斯反演

在莫比烏斯反演中,我們經常需要求\(\sum_{i=1}^n \mu(i) * \lfloor \frac{n}{i} \rfloor\)

在同一段內的和為\(\sum_{i=l}^{r} \mu(i) * \lfloor \frac{n}{l} \rfloor = \lfloor \frac{n}{l} \rfloor \sum_{i=l}^{r} \mu(i) = \lfloor \frac{n}{l} \rfloor (\sum_{i=1}^{r} \mu(i) - \sum_{i=1}^{l-1} \mu(i))\)

使用線性篩可以在\(O(n)\)的時間內預處理所有的\(\sum_{i=1}^{k} \mu(i)\),整除分塊複雜度為\(O(\sqrt{n})\),總複雜度\(O(n)\)

for(int i = 1; i <= n; i++) {
    sum[i] = sum[i - 1] + mu[i];
}
for(int l = 1, r; l <= n; l = r + 1) {
    r = n / (n / l);
    ans += (n / l) * (sum[r] - sum[l - 1]);
}
本文作者: Helium Air     出處:https://www.cnblogs.com/Helium-Air/     版權宣告: 本作品採用 知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議 進行許可。轉載請註明出處!