【学习笔记】数论分块(整除分块)

先看一个例子:

给出正整数 \(n(n \leq 10^{12})\),计算:

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

如果直接暴力,复杂度为 \(O(n)\),无法在 1s 内通过,但使用数论分块(整除分块)可以将复杂度降至 \(O(\sqrt{n})\)

先看个例子,当 \(n = 100\) 时,\(i\)\(\lfloor \frac{n}{i} \rfloor\) 的情况如下:

$i \in $ $\lfloor \frac{n}{i} \rfloor = $
\([1,1]\) \(100\)
\([2,2]\) \(50\)
\([3,3]\) \(33\)
\([4,4]\) \(25\)
\([5,5]\) \(20\)
\([6,6]\) \(16\)
\([7,7]\) \(14\)
\([8,8]\) \(12\)
\([9,9]\) \(11\)
\([10,10]\) \(10\)
\([11,11]\) \(9\)
\([12,12]\) \(8\)
\([13,14]\) \(7\)
\([15,16]\) \(6\)
\([17,20]\) \(5\)
\([21,25]\) \(4\)
\([26,33]\) \(3\)
\([34,50]\) \(2\)
\([51,100]\) \(1\)

我们发现,\(\lfloor \frac{n}{i} \rfloor\) 的取值很少,在本例 \(n = 100\) 中只有 \(19\) 种取值。事实上,对于任意 \(n\)\(\lfloor \frac{n}{i} \rfloor\) 的取值不会超过 \(2 \sqrt{n}\) 种。

证明如下

有一个显然的结论,所有相等的 \(\lfloor \frac{n}{i} \rfloor\) 对应的 \(i\) 是连续的。因此,我们把这段连续的 \(i\) 作为一个“块”来处理(例如 \([26,33]\) 就是一个块)。

由上表格,\(n = 100\) 时总共有 \(19\) 个块。已经证明,块的数量不超过 \(2 \sqrt{n}\),即 \(O(\sqrt{n})\) 级别。

现在的问题在于,在确定了一个块的左端点 \(L\) 之后,如何确定块的右端点 \(R\)

可以证明:

\[R = \lfloor \frac{n}{\lfloor \frac{n}{L} \rfloor} \rfloor \]

证明如下

所以,我们初始设 \(L = 1\),每次将 \(ans\)\(\lfloor \frac{n}{L} \rfloor \times (R - L + 1)\),最后将 \(L\) 设为 \(R + 1\) 再进入下一轮循环。

例题1:余数求和

本题需要用到取模的性质 \(k \bmod i = k - i \times \lfloor \frac{k}{i} \rfloor\),这样原题就转化为求

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

考虑用数论分块求后一项。其余是一样的套路,只需要每次将 \(ans\)

\[\lfloor \frac{k}{L} \rfloor \times \sum_{i = L}^{r} i \]

\[\frac{\lfloor \frac{k}{L} \rfloor \times (L + R) \times (R - L + 1)}{2} \]

另外,因为 \(n,k\) 的大小关系不确定,所以当 \(L > k\)\(\lfloor \frac{k}{L} \rfloor = 0\),可以直接退出循环。

#include<bits/stdc++.h>
#define int unsigned long long
using namespace std;
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int n,k,l,r;
	cin >> n >> k;
	int ans = n * k;
	for(l = 1;l <= n;l = r + 1){
		if(k >= l)
			r = min(k / (k / l),n);
		else
			break;
		ans -= ((r - l + 1) * (int)floor(k / l) * (l + r)) >> 1;
	}
	cout << ans;
	return 0;
}
posted @ 2024-04-08 13:20  5t0_0r2  阅读(15)  评论(0编辑  收藏  举报