P2424 约数和

题目背景

Smart最近沉迷于对约数的研究中。

题目描述

对于一个数X,函数f(X)表示X所有约数的和。例如:f(6)=1+2+3+6=12。对于一个X,Smart可以很快的算出f(X)。现在的问题是,给定两个正整数X,Y(X<Y),Smart希望尽快地算出f(X)+f(X+1)+……+f(Y)的值,你能帮助Smart算出这个值吗?

输入输出格式

输入格式:

 

输入文件仅一行,两个正整数X和Y(X<Y),表示需要计算f(X)+f(X+1)+……+f(Y)。

 

输出格式:

 

输出只有一行,为f(X)+f(X+1)+……+f(Y)的值。

 

输入输出样例

输入样例#1: 
2 4
输出样例#1: 
14
输入样例#2: 
123 321
输出样例#2: 
72543

说明

对于20%的数据有1≤X<Y≤105。

对于60%的数据有1≤X<Y≤1*107。

对于100%的数据有1≤X<Y≤2*109。

Solution:

  本题数论分块。。。

  首先很容易想到前缀和的思想,求$x\rightarrow y$的约数和,也就等于求$1\rightarrow y$的约数和减去$1\rightarrow x-1$的约数和。

  那么在$1\rightarrow n$中会出现的约数显然有$n$个(即$1\rightarrow n$每个数都可作为约数),则对于约数$d,\;d\in[1,n]$,其对约数和的贡献为$d\times \lfloor{n/d}\rfloor$,即$ans=\sum\limits_{i=1}^{n}{(i\times\lfloor{n/i}\rfloor)}$。

  然后对于$i\times\lfloor{n/i}\rfloor$直接数论分块套上等差数列求和就好了。

代码:

 1 #include<bits/stdc++.h>
 2 #define il inline
 3 #define ll long long
 4 #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
 5 #define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--)
 6 #define Max(a,b) ((a)>(b)?(a):(b))
 7 #define Min(a,b) ((a)>(b)?(b):(a))
 8 using namespace std;
 9 ll x,y;
10 
11 il ll solve(ll x){
12     if(x==1)return 0;
13     ll ans=0,p=0;
14     for(ll i=1;i<=x;i=p+1){
15         p=x/(x/i);
16         ans+=(x/i)*(i+p)*(p-i+1)/2;
17     }
18     return ans;
19 }
20 
21 int main(){
22     ios::sync_with_stdio(0);
23     cin>>x>>y;
24     cout<<solve(y)-solve(x-1);
25     return 0;
26 }

猜你喜欢

转载自www.cnblogs.com/five20/p/9199559.html