Editorial for Imperfecciones
Submitting an official solution before solving the problem yourself is a bannable offence.
Author:
Si es la suma de los divisores de , entonces la solución es simplemente . Entonces, necesitamos calcular todos los eficientemente.
Sabemos que la suma de los divisores de un número se puede calcular a partir de sus divisores primos. Si , donde cada es un primo distinto, y es un entero no negativo; entonces la suma de los divisores de es:
Si lo vemos recurrentemente:
Para sacar los primos, usaremos la criba extendida.
Criba Extendida:
Computemos para cada número, un primo que lo divida. O sea, tendremos la tabla p[]
, donde p[i]
es un primo divisor de i
. Para hacerlo, primero consideramos que todos los números son primos (es decir, p[i] = i
); luego iteramos por todos los números i
, y si el número actual es primo (p[i]==i
), iteramos por sus múltiplos j
, y actualizamos p[j] = i
. Se le pueden hacer unas pequeñas optimizaciones para obtener complejidad .
Una vez teniendo p[]
, podemos usar la recurrencia de arriba para calcular para cada .
Código de ejemplo:
for(int i = 3; i <= 1e7; i+=2)
p[i] = i;
for(int i = 2; i <= 1e7; i+=2)
p[i] = 2;
for(int i = 3; i * i <= 1e7; i+=2)
if(p[i] == i)
for(int j = i*i; j <= 1e7; j+=2*i)
p[j] = i;
sigma[1] = 1;
for(int i = 2; i < maxn; i++){
int j = i;
long long k = p[i];
while(j % p[i] == 0){
j /= p[i];
k *= p[i];
}
k = (k - 1)/(p[i] - 1);
sigma[i] = sigma[j] * k;
}
long long ans = 0;
for(int i = a; i <= b; i++)
ans += abs(2ll * i - sigma[i]);
Comments