Fear Factoring(数论,除法分块)

Posted 如风如影�

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Fear Factoring(数论,除法分块)相关的知识,希望对你有一定的参考价值。

Fear Factoring

题目链接: link.


题意:给a,b两个数,求a到b所有数的因数和。

题目分析:我们考虑依次枚举1-n中的每一个约数,比如在1-7中,2是2、4、6的约数,3是3、6的约数,4是4的约数,可以发现每一个约数x在1-7中出现的次数是7/x(向下取整),推广到一般情况,对于1-n中的约数x,它最多是n/x个 数 的因子,也就是说,我们要求S(题目描述中有),可以分别求出每一个约数(这里的约数就是1-n中的每一个数)出现的次数并和约数相乘在累加。
比如:
1-n:    1  2 3  4  5  6  7  8  9  10
次数:  10 5 3  2  2  1  1  1  1   1

如果暴力找的话,时间复杂度太高,所以就用到了除法分块,经过观察可以发现,有某个区间的约数,出现的次数是一样的,所以用除法分块将这个区间找到,然后根据数列性质求和。
所谓分块,就是把一段数分成不同的区间,而这些区间的每一个数除以同一个数的值是相同的,所以我们就把这些区间统一处理,就不用再来一个一个遍历

例: 问题中我们假设n = 10。那么我们现在分一下{1},{2},{3},{4,5},{6,7,8,9,10}。

我们知道初始l肯定是等于1,每次算到了r后,再把l更新到r + 1即可。那么关键是r怎么确定?
先一步一步解释: (n / l)代表的是值为(n / l)的一类数的评定标准,也是这个区间的每一个数对答案的增长的价值。
那么n / (n/l),就是代表这一类数的最大值(也就是右端点r)。

以下式子都可以用除法分块

#include <bits/stdc++.h>
using namespace std;
#define ull unsigned long long
ull l,r;
ull solve(ull n)
{
    
    ull sum=0;
    for(ull l=1,r;l<=n;l=r+1)
    {
        r=n/(n/l);//除法分块
        sum=sum+(n/l)*(r-l+1)*(l+r)/2;//等差数列求和
    }//(n/l)为该因子出现的次数   n/(n/l)为出现该因子次数的最大因子。
    return sum;  
}
int main()
{
    ull a,b;
    cin>>a>>b;;
    cout<<solve(b)-solve(a-1)<<endl;
    return 0;
}

以上是关于Fear Factoring(数论,除法分块)的主要内容,如果未能解决你的问题,请参考以下文章

Fear Factoring(数论,除法分块)

Fear Factoring(数论,除法分块)

Fear Factoring Gym - 101615C(除法分块)

Gym-101615C-Fear Factoring(数论)

2017-2018 ACM-ICPC Pacific Northwest Regional Contest (Div. 2) P-Fear Factoring 区间内数的所有因数的和

《夜深人静写算法》数论篇 - (23) 整数分块