洛谷P2261 整除分块模板

题意:

给出n,kn,kn,k,求出
∑i=1nk mod i \sum_{i=1}^{n}k\ mod\ i i=1nk mod i

Solution:

由于k mod i=k−⌊ki⌋⋅ik\ mod\ i=k-\lfloor\frac{k}{i}\rfloor\cdot ik mod i=kiki,于是只需要求
nk−∑i=1n⌊ki⌋⋅i nk-\sum_{i=1}^{n}\lfloor\frac{k}{i}\rfloor\cdot i nki=1niki
对于一段使⌊ki⌋\lfloor\frac{k}{i}\rfloorik相同的iii,可以利用等差数列求和这一段

现在考虑对于一个lll,如何找到最大的rrr满足
⌊kl⌋=⌊kr⌋ \lfloor\frac{k}{l}\rfloor=\lfloor\frac{k}{r}\rfloor lk=rk
有这样的等式满足
⌊kl⌋=⌊kr⌋≤kr \lfloor\frac{k}{l}\rfloor=\lfloor\frac{k}{r}\rfloor\leq\frac{k}{r} lk=rkrk
于是
r≤k⌊kr⌋=k⌊kl⌋⇒rmax=⌊k⌊kl⌋⌋ r\leq\frac{k}{\lfloor\frac{k}{r}\rfloor}=\frac{k}{\lfloor\frac{k}{l}\rfloor}\Rightarrow r_{max}=\lfloor\frac{k}{\lfloor\frac{k}{l}\rfloor}\rfloor rrkk=lkkrmax=lkk

此时找出了最大的[l,r][l,r][l,r]使⌊kl⌋=⌊kr⌋\lfloor\frac{k}{l}\rfloor=\lfloor\frac{k}{r}\rfloorlk=rk,只需要对r+1r+1r+1作为新的左端点时重新计算即可,并且当⌊kl⌋=0\lfloor\frac{k}{l}\rfloor=0lk=0时,r=+∞r=+\inftyr=+。无论何种情况,切莫忘记题目≤n\leq nn的限制

时间复杂度

i⋅j=ki\cdot j=kij=k

i≤ni\leq \sqrt{n}in时,j≥nj\geq \sqrt{n}jn,此时iii最多n\sqrt{n}n种取值,对应的jjj只可能有一个取值,于是此时最多有n\sqrt{n}n⌊ki⌋\lfloor\frac{k}{i}\rfloorik

同理对i≥ni\geq \sqrt{n}in,此时相当于i,ji,ji,j轮换,取值种数仍然是n\sqrt{n}n

于是总取值不超过2n2\sqrt{n}2n种,时间复杂度O(n)O(\sqrt{n})O(n)

// #include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
#include<bitset>
#include<map>
using namespace std;

using ll=long long;
const int N=1e5+5,inf=0x3fffffff;
const long long INF=0x3fffffffffffffff,mod=1e9+7;

ll n,k;

int main()
{
    cin>>n>>k;
    ll l=1,ans=1ll*n*k;
    while(l<=n)
    {
        ll val=k/l,r=val?min(n,k/val):n;
        ans-=1ll*(l+r)*(r-l+1)/2*val;
        l=r+1;
    }
    cout<<ans;
    return 0;
}
<think>好的,我现在需要帮助用户理解整除分块算法的概念和实现方法。首先,我得回顾一下自己关于整除分块的知识,确保准确无误。 整除分块,我记得是用来快速计算形如$\sum_{i=1}^n \lfloor \frac{n}{i} \rfloor$这样的和的算法。因为当i增大时,$\lfloor \frac{n}{i} \rfloor$的值会分成多个连续的区间,每个区间内的值相同。例如,当n=10时,i=1到10对应的$\lfloor 10/i \rfloor$分别是10,5,3,2,2,1,1,1,1,1。可以看出,很多连续的i对应的结果相同,比如i=5和6时结果都是2,i从7到10都是1。整除分块就是利用这一点,将相同值的区间分块处理,减少计算次数,提高效率。 接下来,我需要解释这个算法的核心思想。用户提供的引用里提到,整除分块的关键是找到这些连续区间的右端点r。对于每个左端点l,对应的r应该是最大的整数,使得$\lfloor \frac{n}{l} \rfloor = \lfloor \frac{n}{r} \rfloor$。根据数学推导,这个r通常是$\lfloor \frac{n}{\lfloor \frac{n}{l} \rfloor} \rfloor$。不过要注意不能超过n本身。 然后是实现方法。代码模板的大致流程是:初始化l为1,然后循环计算每个块的r,累加该块的贡献(即块的长度乘以该块的值),然后将l更新为r+1,直到l超过n。这个过程需要确保r不超过n,避免数组越界。用户提供的引用中的代码示例可以借鉴,但要注意语法是否正确。例如,用户引用中的代码用了min({n, n/(n/l)}),这里可能需要调整,因为n/(n/l)可能不是整数,或者应该用整数除法处理。正确的做法可能是r = min(n, n // (n // l)),在Python中需要用整除符号//,而用户提供的代码可能是C++的语法。 然后需要考虑如何将这些步骤用中文清晰地解释出来,结构要符合用户的要求:分步骤说明,包含概念、数学原理、实现步骤和示例。同时,引用用户提供的三个参考资料,正确标注引用标识。例如,在说明分块思想时引用[^1],在代码部分引用[^2],在数学公式部分引用[^3]。 可能遇到的问题包括如何正确推导r的值,以及如何处理边界情况。例如,当l超过n时循环终止,或者当n/l的商为0时的情况。不过通常当l超过n时,循环会自然结束,因为在循环条件中已经检查了l <= n。此外,每个块的贡献是(r - l + 1)乘以当前的值,即$\lfloor \frac{n}{l} \rfloor$,这部分需要明确说明。 最后,生成相关问题。根据用户提供的示例,问题应围绕整除分块的应用、优化、复杂度分析以及与其它算法的比较等方面展开。比如,如何分析时间复杂度,整除分块的优化方法,实际应用场景等。 总结一下,回答的结构应该是: 1. 概念:简要介绍整除分块是什么,解决什么问题。 2. 数学原理:解释为什么值会分块,如何找到每个块的右端点。 3. 实现步骤:分步骤说明算法流程,给出代码示例。 4. 示例分析:用具体数字举例说明。 5. 相关问题:提出几个相关问题供用户进一步学习。 需要确保所有数学公式使用正确的LaTeX格式,行内公式用$...$,独立公式用$$...$$。同时检查引用标识是否正确添加,如引用[1]、[2]、[3]分别对应用户提供的三个参考资料。</think>### 整除分块算法详解 #### 1. 核心概念 整除分块是一种用于快速计算形如 $\sum_{i=1}^n \lfloor \frac{n}{i} \rfloor$ 的和的算法。其核心思想是**将相同的 $\lfloor \frac{n}{i} \rfloor$ 值划分为连续区间(块)**,通过分块计算减少运算次数,将时间复杂度从 $O(n)$ 优化到 $O(\sqrt{n})$[^1]。 #### 2. 数学原理 - **分块依据**:当 $i$ 增大时,$\lfloor \frac{n}{i} \rfloor$ 的值会形成多个连续区间。例如,$n=10$ 时: $$i=1 \to 10,\quad i=2 \to 5,\quad i=3 \to 3,\quad i=4-5 \to 2,\quad i=6-10 \to 1$$ - **右端点公式**:对于每个块的左端点 $l$,右端点 $r$ 满足: $$r = \min\left(n, \left\lfloor \frac{n}{\lfloor n/l \rfloor} \right\rfloor\right)$$ 该公式保证 $\lfloor \frac{n}{l} \rfloor = \lfloor \frac{n}{r} \rfloor$。 #### 3. 实现步骤 1. **初始化**:左端点 $l=1$,总和 $ans=0$。 2. **循环分块**: - 计算当前块的右端点 $r$。 - 累加当前块的贡献:块长度 $(r-l+1)$ × 块值 $\lfloor \frac{n}{l} \rfloor$。 - 更新左端点 $l = r + 1$。 3. **终止条件**:当 $l > n$ 时结束循环。 **代码实现(Python)**: ```python def division_block(n): ans = 0 l = 1 while l <= n: q = n // l r = n // q if q != 0 else n # 防止除零错误 r = min(r, n) ans += (r - l + 1) * q l = r + 1 return ans ``` #### 4. 示例分析 以 $n=10$ 为例: - **块1**:$l=1$,$q=10$,$r=1$,贡献 $1×10=10$。 - **块2**:$l=2$,$q=5$,$r=2$,贡献 $1×5=5$。 - **块3**:$l=3$,$q=3$,$r=3$,贡献 $1×3=3$。 - **块4**:$l=4$,$q=2$,$r=5$,贡献 $2×2=4$。 - **块5**:$l=6$,$q=1$,$r=10$,贡献 $5×1=5$。 **总和**:$10+5+3+4+5=27$[^2]。 #### 5. 复杂度分析 - **时间复杂度**:$O(\sqrt{n})$。因为 $\lfloor \frac{n}{i} \rfloor$ 的取值最多有 $2\sqrt{n}$ 种(证明需数论知识)。 - **空间复杂度**:$O(1)$,仅需常数级变量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值