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 Gym - 101615C(除法分块)
Gym-101615C-Fear Factoring(数论)
2017-2018 ACM-ICPC Pacific Northwest Regional Contest (Div. 2) P-Fear Factoring 区间内数的所有因数的和