设d(n)定义为n的适当除数之和(小于n的数,它均匀地划分为n)。如果d(a) = b和d(b) = a,其中a ≠ b,那么a和b是友好的对,a和b中的每一个都被称为友好数。
例如,220的适当除数是1、2、4、5、10、11、20、22、44、55和110;因此d(220) = 284。284的适当除数为1、2、4、71和142;so _ d(284) = 220。
评估所有友好人数少于10000的总和。下面是我在Python中的实现。我需要你对如何改进这个问题的反馈。
注:我是编程初学者。
from time import time
def get_divisors(n):
"""Yields divisors of n."""
divisor = 2
while divisor * divisor <= n:
if n % divisor == 0 and n // divisor != divisor:
yield divisor
if n // divisor != divisor:
yield n // divisor
divisor += 1
yield 1
def get_sum_amicable(n, divs={2:1}):
"""Yields amicables below n."""
for number1 in range(n):
for number2 in range(number1):
try:
if divs[number2] == number1 and divs[number1] == number2:
yield number1
yield number2
except KeyError:
divs[number1] = sum(get_divisors(number1))
divs[number2] = sum(get_divisors(number2))
if divs[number2] == number1 and divs[number1] == number2:
yield number1
yield number2
if __name__ == '__main__':
start = time()
print(sum(get_sum_amicable(10000)))
print(f'Time: {time() - start} seconds.')发布于 2019-07-19 08:20:06
def get_sum_amicable(n, divs={2:1}):
"""Yields amicables below n."""
for number1 in range(n):
for number2 in range(number1):
try:
if divs[number2] == number1 and divs[number1] == number2:
yield number1
yield number2
except KeyError:
divs[number1] = sum(get_divisors(number1))
divs[number2] = sum(get_divisors(number2))
if divs[number2] == number1 and divs[number1] == number2:
yield number1
yield number2这太可怕了。它违反了“不要重复自己”的规则;它期望异常作为非例外流的一部分;它依赖于一个模糊的语言特性/错误特性。
您所需要做的就是求和数x in range(n) (或者,也许更好的是range(2, n),以避免0和1周围的复杂情况),对于它,d(x) < n and d(d(x)) == x。(考虑到问题的措辞方式,您可能会假设不会有围绕n的友好对,因此测试的前半部分可能是不必要的)。这是一条单线。
如果要缓存d,则可以使用functools.lru_cache而不是使用默认值。但是..。
每当您对从1到n的每个数字进行可分性检查时,都应该考虑使用筛子。要么构建一个由每个数的一个素因子组成的数组,然后以此为基础工作,要么(在适当的情况下)将计算嵌入到筛子处理中。
很容易调整Eratosthenes的筛子,使用内联方法高效地生成一个d数组。
https://codereview.stackexchange.com/questions/224461
复制相似问题