[数学基础] 10 数论分块
作者:互联网
数论分块
简介
数论分块通常被用来以\(O(\sqrt n)\)的复杂度快速计算形如\(\sum \limits_{i=1}^n f(i)g(\lfloor \frac n i \rfloor)\)的含有除法向下取整的和式,它的核心思想是将\(\lfloor \frac n i \rfloor\)相同的数打包同时计算,主要利用了Fubini定理。
证明
1. 证明时间复杂度为\(O(\sqrt n)\)
引理1 对于任意一个正整数\(n\),\(\lfloor \frac n d \rfloor(d\in[1,n])\)的数量级为\(\sqrt n\)。
- \(d\leq \sqrt n\),假设所有的\(\lfloor \frac n d \rfloor\)取值均不同,则存在\(\sqrt n\)种结果
- \(d>\sqrt n\),则\(\lfloor \frac n d \rfloor<\sqrt n\),取值同样有\(\sqrt n\)。
因此,所有的可能取值一定\(\leq 2\sqrt n\),即整数分块的复杂度为\(O(\sqrt n)\)。
2. 证明算法的正确性
引理2 对于\(\forall i\), 若满足\(\lfloor \frac{n}{i} \rfloor=C\),则所有满足条件的\(i\)一定是一段连续区间的集合。
反证法,若不是连续区间,则一定\(\exist t\in(l,r)\),使得\(\lfloor \frac{n} l \rfloor=\lfloor \frac n r \rfloor\)且\(\lfloor \frac n l \rfloor \neq \lfloor \frac n t \rfloor\)。
\(\because t>l,t<r\)
\(\therefore \lfloor \frac n t \rfloor \geq \lfloor \frac n l \rfloor, \lfloor \frac n t \rfloor \leq \lfloor \frac n r \rfloor\) ,即\(\lfloor \frac n t \rfloor=\lfloor \frac n l \rfloor\),矛盾,故得证。
**引理3 **若满足\(\lfloor \frac n i \rfloor=C\)的\(i\)集合为\(i\in[l,r]\),则只需要知道\(l\),就可以求出对应的\(C,r\)。
显然,\(C=\lfloor \frac n l \rfloor\),下面就要证明\(r=\lfloor \frac{n}{\lfloor \frac n l \rfloor} \rfloor=\lfloor \frac n C \rfloor\)
令\(p=\lfloor \frac n C \rfloor\),则\(n=p\times C+k,k\in[0,\min\{p,C\})\),下面要证明\(p\)是满足\(i\)的性质的最大的整数。
- \(p\)满足\(i\)的性质,即\(\lfloor \frac n p \rfloor=C\)
\(p=\frac{n-k}{C}\),则\(\frac n p=\frac{C\times n}{n-k}\geq \frac {C\times n}{n}\),即\(\frac n p \geq C\)。
又\(n\mod p=k,k<p\),则\(n-k<p\times (C+1)\),即\(\lfloor \frac n p \rfloor<C+1\)
因此\(\lfloor \frac n p \rfloor=C\)
- \(p\)是使得\(\lfloor \frac n i \rfloor=C\)成立的最大的数。
反证法,假如\(p\)不是最大的数,则\(p+1\)一定可以使得\(\lfloor \frac n {p+1} \rfloor=C\)
\(\therefore (p+1)\times C=n-g(g\in[0,\min\{p+1,C\})\)
\(\therefore p\times C + C=n-g\),又\(p\times C=n-k\)
所以\(C=k-g\),又\(k,g\in[0,C)\),所以矛盾,得证。
综上,\(\lfloor \frac n C \rfloor\)即为令\(\lfloor \frac n i \rfloor=C\)的最大的数
模板
ll H(ll n){
ll res = 0, l = 1, r;
while (l <= n){
r = n / (n / l);
res = res + (r - l + 1) * (n / l);
l = r + 1;
}
return res;
}
例题
P2261余数之和
给出\(n,k\),计算\(G(n,k)=\sum\limits _{i=1}^n k \bmod i\)
数据范围:\(1\leq n,k\leq 10^9\)
(懒得自己写题解了,直接cpy洛谷题解orz)由题意得:\(ans=∑_{i=1}^nk\bmod i\)
我们知道,\(a \bmod b = a - b \times \lfloor \frac{a}{b} \rfloor\)
因此,\(ans = \sum_{i=1}^{n} k - i \times \lfloor \frac{k}{i} \rfloor = nk - \sum_{i=1}^{n} i \times \lfloor \frac{k}{i} \rfloor\)
首先枚举块的左边界 \(l\),并根据左边界和$ k$ 计算出右边界 \(r\)。
令 \(t = \lfloor \frac{k}{l} \rfloor\),分两种情况讨论:
- \(t \neq 0\),则 \(r = \min (\lfloor \frac{k}{t} \rfloor , n)\);
- \(t = 0\),则 \(r = n\)。
右边界有了,每一块的和也就可以计算出了。
每一块的和 \(=\) 当前块的 \(t\times\) 当前块元素个数 \(\times\) 当前块 \(i\) 的平均值 \(= t \times (r-l+1) \times (l+r) \div 2\)
当前块处理完后,令 \(l = r + 1\),开始计算下一块,直到计算至 n。
ll n, m;
void solve(){
n = read(), m = read();
ll res = n * m, l = 1, r;
while (l <= n){
if (m / l == 0) r = n;
else r = min(n, m / (m / l));
res = res - (r - l + 1) * (m / l) * (l + r) / 2;
l = r + 1;
}
printf("%lld\n", res);
}
数论分块往往和莫比乌斯反演结合起来考察,因此进阶的部分放在可能会存在的莫反专题中一起讲解。
标签:lfloor,10,frac,分块,数论,ll,rfloor,times,sqrt 来源: https://www.cnblogs.com/vivaldi370/p/MathBasic_10_sqrt-decomposition.html