分块除法 Fear Factoring

The Slivians are afraid of factoring; it's just, well, difficult.

Really, they don't even care about the factors themselves, just how much they sum to.

We can define F(n)F(n) as the sum of all of the factors of nn; so F(6) = 12F(6)=12 and F(12) = 28F(12)=28. Your task is, given two integers aa and bb with a ≤ ba≤b, to calculate S = \sum_{a≤n≤b} F(n)S=∑a≤n≤b​F(n). 

1 Input

The input consists of a single line containing space-separated integers aa and bb (1 ≤ a ≤ b ≤ 10^{12}; b-a ≤ 10^{6} )(1≤a≤b≤1012;b−a≤106).

2 Output

Print SS on a single line. 

样例输入复制

101 101
28 28
1 10
987654456799 987654456799
963761198400 963761198400
5260013877 5260489265

样例输出复制

102
56
87
987654456800
5531765944320
4113430571304040

https://www.it610.com/article/1289920140560900096.htm(大佬讲的好)

 

显然是要枚举因子算贡献,

然后要搞前缀和算[1,r]-[1,l-1]

两种做法,

一个是这次要学的援引的博主的做法……

另一个是自己瞎搞搞出来的,先枚举数出现的次数,再枚举数的值,两个1e6能摊出来

 

可以看出,一段区间的出现次数都是相同的,那我们不妨枚举区间

这个区间的段数不会超过1e6

比如对于n=10,可分成这些段[1][2][3][4,5][6,10]

分别出现10次,5次,3次,2次,1次

那么,对于当前端点l,l出现了n/l次,

而同样出现n/l次的数,最大为r=n/(n/l),

这个向下取整的操作真的惊艳啊

那么对于[l,r]这段区间的数都出现了n/l次,

其贡献为(l+r)*(r-l+1)/2*(n/l),

然后令l=r+1,去统计下一段区间的贡献即可

 

# include <iostream>
# include <algorithm>
# include <cstring>
# include <math.h>
# include <stdio.h>
# include <vector>
# include <map>
using namespace std;
# define ll long long
# define ull unsigned long long
ull get(ull n){
	ull r;
	ull ans = 0;
	for(ull l = 1; l <= n; l = r+1){
		r = n/(n/l);
		ans += (l+r)*(r-l+1)*(n/l)/2;
	}
	return ans;
}
int main(){
	
	ull a,b;
	while(cin >> a >> b){
		cout << get(b) - get(a-1) << endl;
	}
	
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值