整除分块(数论分块)

整除分块

整除分块是为了解决一个整数的求和问题:
在这里插入图片描述
如果直接暴利计算,复杂度是O(n)的,若n很大会超时。但是,用整除分块来求解,复杂度是O(n1/2)的。
下面以n==8为例,列出每个情况:
在这里插入图片描述
对第二行求和,结果是20

观察上面第二行 8 / i 的值发现是逐步变小的,并且很多相等,这是整除操作的规律。例如:
8/1 = 8
8/2 = 4
8/3 = 8/4 =2
8/5 = 8/6 = 8/7 = 8/8 =1

为了对这些整数的结果快速求和,自然能想到,把它们分成一块一块的,其中每一块的 8 / i 相同,把这一块一起算,就快多了。

设每一块的左右区间是[ l , r ],上面的例子可以分成4块:[ 1 , 1 ]、
[ 2 , 2 ]、[ 3 , 4 ]、[ 5 , 8 ]。
每一块内部的求和计算,只要用数量乘以值就行了,这个计算的复杂度是O(1)的。

最后还有两个问题:
(1)按相同的值分块,一共需要分成几块
【答】分块少于2n1/2种,证明如下:

(a)i<=n1/2时,n/i的值有{ n/1,n/2,n/3,… n/n1/2} 共n1/2个。

(b)i>n1/2 时,有 n / i < n1/2 此时也有n1/2种取值。

两者相加,共2n1/2种。

(2)如何计算?或者说,给定每个块的第一个数l,能推出这个块的最后一个数r吗?

【答】可以证明:r = n/(n/l)。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int main()
{
    LL n,ans=0;
    cin>>n;
    for(LL l=1,r;l<=n;l=r+1)
    {
        r=n/(n/l);
        ans+=(r-l+1)*(n/l);
    }
    cout<<ans;
    system("pause");
    return 0;
}
  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值