题目背景
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)的值。
输入输出样例
说明
对于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 }