Luogu P2424 约数和
题意:f(n)表示n的约数的和。给定x,y,求f(x)+f(x+1)+...+f(y)。
暴力枚举显然不行。
枚举一个数的约数会有很多重复的,考虑改为求1~n的倍数
(n/i)表示1~n中i的倍数的个数(i,2i,3i...(n/i)i)
即 f(n) = Sum((n/i)*i) (i=1~n)
那么答案即为f(y)-f(x-1)
复杂度$O(y)$,继续优化
比如f(8) = 8*1 + 4*2 + 2*3 + 2*4 + 1*5 + 1*6 + 1*7 + 1*8
发现(n/i)的部分有很多重复的,i又可以写成等差数列的形式
所以把重复的用区间表示
设区间[l,r]内,n/i的值相等。
初始l=1,每次l=上一个r+1;
满足倍数有n/i个的最大的数是n/(n/i),
即r = n/(n/l)
i的部分写成等差数列,即(r-l+1)*(l+r)/2
得f(n) = Sum( (n/l)*(r-l+1)*(l+r)/2 ) (r<=n)
代码如下
#include<cstdio> #include<iostream> #include<cmath> #include<cstring> #define MogeKo qwq using namespace std; long long x,y; long long sum(long long n){ long long l,r,ans = 0; for(l = 1;l <= n;l = r+1){ r = n/(n/l); ans += (n/l)*(r-l+1)*(l+r)/2; } return ans; } int main(){ scanf("%lld%lld",&x,&y); printf("%lld",sum(y)-sum(x-1)); return 0; }