#G. Encuentra el sexto del divisor.


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;
}

Supongo que te gusta

Origin blog.csdn.net/weq2011/article/details/129191269
Recomendado
Clasificación