estoy tratando de resolver this Project Euler question:Optimizar sumas no abundantes algoritmo
Un número perfecto es un número para el que la suma de sus divisores propios es exactamente igual al número. Por ejemplo, la suma de los divisores adecuados de de 28 sería 1 + 2 + 4 + 7 + 14 = 28, lo que significa que 28 es un número perfecto.
Un número n se llama deficiente si la suma de sus divisores propios es menor que ny se llama abundante si esta suma excede n.
Como 12 es el número abundante más pequeño, 1 + 2 + 3 + 4 + 6 = 16, la número más pequeño que se puede escribir como la suma de dos números abundantes es de 24. Por análisis matemático, puede ser se muestra que todos los enteros mayor que 28123 se pueden escribir como la suma de dos números abundantes. Sin embargo, este límite superior no puede reducirse más mediante el análisis aunque se sabe que el mayor número que no puede ser expresado como la suma de dos números abundantes es menor que este límite.
Encuentra la suma de todos los enteros positivos que no pueden escribirse como la suma de dos números abundantes.
Mi solución:
#returns a list of the divisors of a given number
def Divs(Number):
Divisors = []
for i in range(2 , int(Number**0.5) + 1):
if Number % i == 0:
Divisors.append(i)
for q in range(len(Divisors)):
if Divisors[q] != (Number/Divisors[q]):
Divisors.append(Number/Divisors[q])
Divisors.insert(0,1)
return Divisors
#returns a list of abundant numbers up to and including the limit
def AbList(limit):
Abundant = []
for i in range(11,limit + 1):
if sum(Divs(i)) > i:
Abundant.append(i)
return Abundant
#Finds the sum of all positive integers that cannot be written as the
#sum of two abundant numbers...
def AbSum(limit):
Abundant = AbList(limit)
NoAbSum = 0
for i in range(1 , limit):
AbSum = 0
x = 0
for x in Abundant:
if i - x in Abundant[:i]:
AbSum = 1
break
if AbSum == 0:
NoAbSum += i
return NoAbSum
Esto llevó a mi procesador de 3,4 GHz aproximadamente 15 minutos para resolver y estoy en busca de una mejor manera. No me preocupan las primeras dos funciones porque juntas tardan menos de un segundo en ejecutarse. La tercera función es el kicker aquí. Corre a través del rango de números hasta el límite (en este caso, 20000 y algo), y cada vez, recorre la lista de números abundantes, restando cada uno del número actual, luego verificando esa respuesta contra la lista de abundantes números. Si hay una coincidencia, el bucle se rompe e intenta nuevamente con el siguiente número, todo el camino hasta el límite.
Sé que tiene que haber una mejor manera de hacerlo, pero soy algo nuevo en la programación. ¿Cómo puedo acelerar este algoritmo?
Su solución actual es 'O (m * n)', donde 'm' (el límite) es mucho mayor que' n' (el número de números abundantes inferiores al límite). Ahora, ¿cuál sería la complejidad temporal de calcular todos los números que * son * sumas de otros números abundantes? ¿Eso es mejor o peor que tu solución actual? –
¿Por qué estás ordenando los divisores? –
Una vez que envíe la solución correcta, tendrá acceso al hilo de discusión para ese problema donde encontrará algunas de las soluciones más eficientes. – kefeizhou