数学--数论--整除分块(巨TM详细,学不会,你来打我)

1.概念
从一道例题说起
在 介 绍 整 除 分 块 之 前 , 我 们 先 来 看 一 道 算 数 题 : 已 知 正 整 数 n , 求 ∑ i = 1 n ⌊ n i ⌋ 已 知 正 整 数 n , 求 ∑ i = 1 n ⌊ n i ⌋ 在介绍整除分块之前,我们先来看一道算数题: 已知正整数n,求∑i=1n⌊ni⌋\begin{aligned}已知正整数n,求\sum_{i=1}^n \left⌊\dfrac{n}{i}\right⌋\end{aligned} ni=1nnini=1nin

我们写一个表格看一看1-20的整除是什么样子的

i1234567891011121314151617181920
⌊ 20 i ⌋ \left⌊\dfrac{20}{i} \right⌋ i202010654322221111111111

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

2.整除分块公式推导

向下取整的情形
还是说我们的例题
已 知 正 整 数 n , 求 ∑ i = 1 n ⌊ n i ⌋ 已知正整数n,求\sum_{i=1}^n \left⌊\dfrac{n}{i}\right⌋ ni=1nin
 假设我们已知某一个分块的左端点lll,要求解出该分块的右端点rrr。设该分块的数值为kkk,对于该分块中的每个数iii,有 k = ⌊ n i ⌋ = ⌊ n l ⌋ k=\left⌊\dfrac{n}{i}\right⌋=\left⌊\dfrac{n}{l}\right⌋ k=in=ln,即 i k ≤ n ik\le n ikn,也就是说我们找到可得使 i k ≤ n ik\le n ikn成立的最大的i的值即是我们所求的右端点r,因此我们可以得到下列式子:

{ k = ⌊ n l ⌋   r = max ⁡ ( i ) , i k ≤ n \begin{cases}k = \left⌊\dfrac{n}{l}\right⌋ \\\space \\r = \max (i), ik \le n\end{cases} k=ln r=max(i),ikn

推导可得:

r = ⌊ n k ⌋ = ⌊ n ⌊ n l ⌋ ⌋ r= \left⌊\dfrac{n}{k}\right⌋=\left⌊\dfrac{n}{\left⌊\dfrac{n}{l}\right⌋ }\right⌋ r=kn=lnn

容易得到代码:

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

But 还没有结束

我们再看这一道题:

已 知 正 整 数 n , a , b , 求 ∑ i = 1 n ⌊ n a i + b ⌋ \begin{aligned}已知正整数n, a, b, 求\sum_{i=1}^n \left⌊\dfrac{n}{ai + b} \right⌋\end{aligned} n,a,b,i=1nai+bn

抓瞎了,但是变变形应该可以做。

我们记得

{ k = ⌊ n l ⌋   r = max ⁡ ( i ) , i k ≤ n \begin{cases}k = \left⌊\dfrac{n}{l}\right⌋ \\\space \\r = \max (i), ik \le n\end{cases} k=ln r=max(i),ikn
r = ⌊ n k ⌋ = ⌊ n ⌊ n l ⌋ ⌋ r= \left⌊\dfrac{n}{k}\right⌋=\left⌊\dfrac{n}{\left⌊\dfrac{n}{l}\right⌋ }\right⌋ r=kn=lnn
以上两个公式,我们有如下
{ k = ⌊ n a l + b ⌋   r = max ⁡ ( i ) , ( a i + b ) k ≤ n \begin{cases}k = \left⌊\dfrac{n}{al+b}\right⌋ \\\space \\r = \max (i), (ai+b)k \le n\end{cases} k=al+bn r=max(i),(ai+b)kn

上式子可推导为


但是对于这个题目,我们给出第二种推导方式,使得一种推导方式解决多种题目。
在这里插入图片描述
这我们再做
已 知 正 整 数 n , 求 ∑ i = 1 n ⌊ n i 2 ⌋ \begin{aligned}已知正整数n, 求\sum_{i=1}^n \left⌊\dfrac{n}{i^2} \right⌋\end{aligned} n,i=1ni2n
我们按照上面的方式推导
在这里插入图片描述
不知道这时候有多少人偷笑,说自己把整除分块学会了,曾经以为自己是个王者,结果他爸来。

在这里插入图片描述
这个题你懵了吗,对于一对 L和R,中间的值是等差数列,相差1,归根结底还是整除分块,还是找到l和r,通过等差数列计算即可。
代码如下:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    long long n, k, ans = 0;
    long long left = 1, right, rest;
    scanf("%lld%lld", &n, &k);
    while (left <= n && left <= k) //求从1到min(n, k)内的总和
    {
        right = min(k / (k / left), n);	
        rest = k % left;
        ans += (rest + rest - (right - left) * (k / left)) * (right - left + 1) / 2;
        left = right + 1;
    }
    if (n > k)
    {
        ans += k * (n - k);
    }
    cout << ans;
}

完后
王者你会了吗?
王者自信满满的说自己会了!

王者再看看这个题

已 知 正 整 数 n , 求 ∑ i = 1 n ⌈ n i ⌉ 已知正整数n,求\sum_{i=1}^n \left⌈\dfrac{n}{i}\right⌉ ni=1nin

没4没4,我们就不推导向上取整了,这里只需要一个小转化,将向上取整转化为向下取整。
我们考虑没有整除的时候是不是就有
⌈ n i ⌉ = ⌊ n i ⌋ + 1 \left⌈\dfrac{n}{i}\right⌉ =\left⌊\dfrac{n}{i}\right⌋+1 in=in+1 如果整除的时候就相等了,那么我们只要不加1,我们加上 i − 1 i \dfrac{i-1}{i} ii1就可以避免这种情况,那么就可以转化为
在这里插入图片描述
通过上面向下取整的推到即可得到
在这里插入图片描述
到这里王者就可以独当一面了。

  • 114
    点赞
  • 251
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值