项目Euler#23 Python
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了项目Euler#23 Python相关的知识,希望对你有一定的参考价值。
所以我正在研究Project Euler#23,我需要一些效率帮助。
好的,原来的问题是:
完美数字是一个数字,其正确除数的总和恰好等于数字。例如,28的适当除数之和为1 + 2 + 4 + 7 + 14 = 28,这意味着28是一个完美数。
如果n的适当除数之和小于n,则数n被称为不足,如果该和超过n,则称其为n。
由于12是最小的有限数,1 + 2 + 3 + 4 + 6 = 16,可以写成两个有限数之和的最小数是24.通过数学分析,可以证明所有整数都大于28123可以写成两个数字的总和。然而,即使已知不能表示为两个充裕数的总和的最大数量小于该限制,也不能通过分析进一步减小该上限。
找到所有正整数的总和,这些正整数不能写为两个数字的总和。
我已经让大部分代码高效运行,但我遇到的一个问题就是找到所有数字都是两个数字的总和。
import math
import time
def factors(n):
fact=[1,n]
check=2
rootn=math.sqrt(n)
while check<rootn:
if n%check==0:
fact.append(check)
fact.append(n/check)
check+=1
if rootn==check:
fact.append(check)
fact.sort()
return fact
abundantNumbers = []
timeStart = time.time()
for i in range(12, 28124):
factorTemp = factors(i)
totalTemp = 0
factorTemp.remove(i)
for j in range(len(factorTemp)):
factorTemp[j] = float(factorTemp[j])
for j in range(len(factorTemp)):
totalTemp+=factorTemp[j]
if totalTemp> i:
abundantNumbers.append(i)
break
nums = []
doubleAbu = []
for i in range(24, 28124):
nums.append(i)
for j in abundantNumbers:
if j*2 < 28123 and j*2 not in doubleAbu:
doubleAbu.append(j*2)
for i in abundantNumbers:
repeat=True
for j in abundantNumbers[abundantNumbers.index(i):]:
if i + j not in doubleAbu and i + j <28123:
doubleAbu.append(i+j)
elif i + j > 28123:
break
repeat = False
if not repeat:
break
total = 0
for i in range(len(doubleAbu)):
nums.remove(doubleAbu[i])
for i in range(len(nums)):
total += nums[i]
print("It took, ", str(time.time()-timeStart), " seconds!")
#print((abundantNumbers))
print(doubleAbu)
print(total)
我已经做了相当多的研究,我确信有数以千计的方法做得比我好,但是如果有人有任何方程或只是更好的方法来找到正整数,这是两个数量的总和我可以使用一些帮助。
您可以只有一个28124布尔值的列表,初始化为False
。然后迭代大量数字,并为每个数字找到数字等于或大于它的所有总和。对于每个和x,在列表True
中设置xth标志。由于数量是按升序排列的,当sum大于28123时,你可以打破内循环。然后在最后一步迭代列表并将所有具有False
值的indeces加在一起:
import math
import time
def factors(n):
fact=[1,n]
check=2
rootn=math.sqrt(n)
while check<rootn:
if n%check==0:
fact.append(check)
fact.append(n//check)
check+=1
if rootn==check:
fact.append(check)
fact.sort()
return fact
abundantNumbers = []
timeStart = time.time()
for i in range(12, 28124):
factorTemp = factors(i)
totalTemp = 0
factorTemp.remove(i)
for j in range(len(factorTemp)):
factorTemp[j] = float(factorTemp[j])
for j in range(len(factorTemp)):
totalTemp+=factorTemp[j]
if totalTemp> i:
abundantNumbers.append(i)
break
MAX = 28123
result = [False] * (MAX + 1)
for i in range(len(abundantNumbers)):
for j in range(i, len(abundantNumbers)):
s = abundantNumbers[i] + abundantNumbers[j]
if s > MAX:
break
result[s] = True
print(sum(i for i, x in enumerate(result) if not x))
print("It took, ", str(time.time()-timeStart), " seconds!")
输出:
4179871
It took, 3.190303325653076 seconds!
有一个更快更短的版本,虽然我很确定它仍然可以改进。
import time
from math import ceil
# Sum of Proper Divisors of
def sopd(n):
if n == 1: return 0
s = 1
sqrt = ceil(n ** 0.5)
for b in range(2, sqrt):
if n % b == 0:
s += (b + n // b)
return s + (sqrt if sqrt ** 2 == n else 0)
if __name__ == '__main__':
start_time = time.time()
abundant = set()
s = 0
for i in range(1,28124):
if not any(i-a in abundant for a in abundant):
s += i
if sopd(i) > i:
abundant.add(i)
print(s)
print("--- {} seconds ---".format(time.time() - start_time))
我的电脑需要大约1.2秒
以上是关于项目Euler#23 Python的主要内容,如果未能解决你的问题,请参考以下文章
Python 中的列表范围 - Project Euler 007
卡在项目 euler 的问题 8 上,得到错误的答案,但代码似乎正确