Primero encontramos la suma de todos los divisores entre el intervalo [1..b]
Entonces el resultado es igual a
La suma de todos los divisores entre [1..b] menos la suma de los divisores entre [1..a-1]
Obviamente estos dos problemas son de la misma naturaleza, sólo que los puntos finales correctos son diferentes.
Obviamente, para números entre 1 y N, el rango del divisor también está dentro del rango de 1 a N.
Entonces podemos enumerar el número aproximado L. Por supuesto, esta enumeración no puede ser una enumeración de bucle for, pero está "saltando" como en la pregunta anterior.
Entonces N/L representa cuántos números entre 1 y N son múltiplos de L, y L también debe ser su divisor.
Por ejemplo, cuando L=7, N=20
N/20=2, indicando que hay dos números dentro del 1 al 20 que son múltiplos de 7, los cuales se conocen fácilmente como 7 y 14, lo que significa que al calcular la suma de los divisores de 7 y 14 se debe contar 7 .
Entonces la inteligencia de este algoritmo es que
Cuando L=8,9,10, N/L=2
Entonces L=7, R=10 en esta sección
Entonces la suma de los divisores en esta sección es 2*7+2*8+2*9+2*10=2*(7+8+9+10)=2*(7+10)*(10-7 + 1)/2
Después de contar esta sección, establezca L=R+1=10+1=11
Verás que el 11 se utiliza como número aproximado y solo aparecerá una vez.
Al mismo tiempo, también encontrará que los números aproximados de 12, 13, 14... 20 en esta sección solo aparecerán una vez.
#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll n,m;
ll f(ll x)
{
ll l = 1,r = 0,k = 0,ans = 0,m = 0;
while(l <= x)
{
r = x / (x / l);
k = x / l;
ans += k * (l + r) * (r - l + 1) / 2;
l = r + 1;
}
return ans;
}
signed main()
{
cin>>n>>m;
cout<<f(m) - f(n - 1);
return 0;
}