浅谈整除分块

模型:

\(\sum_{i=1}^{n}\left\lfloor\frac{n}{i}\right\rfloor\)
假设 \(n = 8\),那么可得:

\(i\)12345678
\(8/i\)84221111

概念:

表中同样的值会连续出现,而相同的值所划分的区间成为一个块。
整除的性质使得从 \(1\) 到 \(n\) 的表可根据数值划分为不同的块,且分块数远远小于 \(n\)。
利用这种性质,我们可以推导出每个分块具体的左右端点位置在哪,这样就可以快速求解出来了。

推导:

假设我们已知某一个分块的左端点 \(l\),要求解出该分块的右端点 \(r\)。
设该分块的数值为\(k\),对于该分块中的每个数\(i\),有 \(k=\left\lfloor\frac{n}{i}\right\rfloor=\left\lfloor\frac{n}{l}\right]\),即 \(i\times k \le n\)。
那么显然满足 \(i \times k \le n\) 成立的最大的 \(i\) 就是我们要的右端点 \(r\)。
于是可得:\(\left\{\begin{array}{l}k=\left\lfloor\frac{n}{l}\right\rfloor \\ r=\max (i), i \times k \leq n\end{array}\right.\)
推导得:\(r=\left\lfloor\frac{n}{k}\right\rfloor=\left\lfloor \frac{n}{\left\lfloor\frac{n}{l}\right\rfloor}\right\rfloor\)

变形0:

已知 \(n,m\),求 \(\sum_{i=1}^{min(n,m)}\lfloor\frac{n}{ i}\rfloor\lfloor\frac{m}{i}\rfloor\)\(\left\{\begin{array}{l}k1=\left\lfloor\frac{n}{l}\right\rfloor,k2= \left\lfloor\frac{m}{l}\right\rfloor\\ r=\max (i), i \times k1 \leq n,i\times k2 \le m\end{array}\right.\)\(r = min(\lfloor\frac{n}{k1}\rfloor,\lfloor\frac{m}{k2}\rfloor)\)

变形1:

已知 \(n,a,b\),求 \(\sum_{i=1}^{n}\left\lfloor\frac{n}{a i+b}\right\rfloor\)
令 \(i' = a\times i + b\),先求出 \(\left\lfloor\frac{n}{i'}\right\rfloor\) 的整除分块
可得 \(k=\left\lfloor\frac{n}{a\times l+b}\right\rfloor\),\(r'=\left\lfloor\frac{n}{k}\right\rfloor=\left\lfloor\frac{n}{\left\lfloor\frac{n}{a \times l + b}\right\rfloor}\right\rfloor\)\(\left\{\begin{array}{l}i'=a\times i +b \\ r'=\max (i')\end{array}\right.\)→\(\begin{cases}a\times i=i'-b\\ i=\dfrac{i'-b}{a}\end{cases}\)→ \(r=max(i)= max(\left\lfloor\frac{i'-b}{a}\right\rfloor) = \lfloor\frac{r'-b}{a} \rfloor\)
$r =\left \lfloor \dfrac{\left \lfloor \dfrac{n}{\lfloor \dfrac{n}{a\times l+b}\rfloor }\right \rfloor -b}{a}\right \rfloor $

变形2:

做法同上。
已知 \(n\),求 \(\sum_{i=1}^{n}\left\lfloor\frac{n}{i^2}\right\rfloor\)
令 \(i' = i^2\),先求出 \(\left\lfloor\frac{n}{i'}\right\rfloor\) 的整除分块
可得 \(k=\left\lfloor\frac{n}{l^2}\right\rfloor\),\(r'=\left\lfloor\frac{n}{k}\right\rfloor=\left\lfloor\frac{n}{\left\lfloor\frac{n}{l^2}\right\rfloor}\right\rfloor\)\(\left\{\begin{array}{l}i=\sqrt{i'} \\ r'=\max (i')\end{array}\right.\) → \(r = max(i) = max(\lfloor\sqrt{i'} \rfloor) = \lfloor r' \rfloor = \lfloor\sqrt{\left\lfloor\frac{n}{\left\lfloor\frac{n}{l^2}\right\rfloor}\right\rfloor}\rfloor\)

变形3:

已知 \(n\),求 \(\sum_{i=1}^{n}\left\lceil\frac{n}{i}\right\rceil\)
当 \(n\) 整除 \(i\) 时,\(\left\lceil\frac{n}{i}\right\rceil = \left\lfloor\frac{n}{i}\right\rfloor\)
当 \(n\) 不整除 \(i\) 时,\(\left\lceil\frac{n}{i}\right\rceil = \left\lfloor\frac{n}{i}\right\rfloor + 1\)
于是我们可以用 $\lfloor \frac{n+i-1}{i}\rfloor $ 来代替 \(\lceil\frac{n}{i}\rceil\)
原式就转换为了 \(\sum_{i=1}^{n}\lfloor\frac{n+i -1}{i}\rfloor\)

那么有 \(\left\{\begin{array}{l}k=\left\lfloor\frac{n+l-1}{l}\right\rfloor \\ r=\max (i), i\times k \leq n+i-1 \end{array}\right.\)\(\because i \times k \le n+i-1 \Rightarrow i\times(k-1) \le n-1\)\(\therefore r=\left\lfloor\frac{n-1}{k-1}\right\rfloor=\left[\frac{n-1}{\left\lfloor\frac{n+l-1}{l} \mid-1\right.}\right\rfloor\)

### Codeforces 平台上的整除分块题目及其解法 #### 1. 整除分块简介 整除分块是一种用于优化求和表达式的技巧,特别适用于处理形如 $\sum_{i=1}^{n}\left\lfloor \frac{n}{i} \right\rfloor$ 的问题。通过观察可以发现,在一定范围内,$\left\lfloor \frac{n}{i} \right\rfloor$ 是相同的,因此可以通过分段来减少重复计算。 #### 2. 应用实例:Codeforces 616E - Sum of Remainders 该题要求计算给定 $n$ 和 $m$ 下的 $\sum_{i=1}^{m}(n \% i)$[^3]。此题的核心在于如何高效地计算模运算的结果之和。利用整除分块的思想,可以将原问题转化为多个子区间内的快速求和操作: ```cpp #include <bits/stdc++.h> using namespace std; long long sum_of_remainder(long long n, long long m) { long long result = 0; for (int l = 1; l <= min(n, m); ) { int r = min(m / ((n / l)), m); if (!r) break; // Calculate the contribution from this block. result += (r - l + 1LL) * (n % l); l = r + 1; } return result; } ``` 上述代码实现了基于整除分块的方法来解决这个问题。具体来说,`l` 表示当前区间的左边界,而 `r` 则表示右边界;每次迭代都会找到一个新的有效区间 `[l,r]` 来加速计算过程。 #### 3. 另一应用案例:Polycarp and Div 3 虽然这道题表面上看起来与整除无关,但实际上也可以借助类似的思维模式来进行解答。题目描述了一个长度为 $n$、元素取值于 $[1,k]$ 的序列,并询问满足某些条件下的方案数量。这里的关键点在于理解 GCD 性质以及组合计数原理的应用[^1]。 为了简化复杂度高的暴力枚举方法,同样可以考虑采用类似于整除分块的方式——即针对不同因子构建对应的贡献矩阵并累加其结果。不过需要注意的是,这类转换通常会涉及到更复杂的数学变换和技术细节。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值