solutions of problem 21 and problem 20
This commit is contained in:
96
solutions/0021.AmicableNumbers/euler_21.py
Normal file
96
solutions/0021.AmicableNumbers/euler_21.py
Normal file
@@ -0,0 +1,96 @@
|
||||
"""
|
||||
Let d(n) be defined as the sum of proper divisors of n (numbers less than n which divide evenly into n).
|
||||
If d(a) = b and d(b) = a, where a ≠ b, then a and b are an amicable pair and each of a and b are called amicable numbers.
|
||||
|
||||
For example, the proper divisors of 220 are 1, 2, 4, 5, 10, 11, 20, 22, 44, 55, and 110; therefore d(220) = 284.
|
||||
The proper divisors of 284 are 1, 2, 4, 71, and 142; so d(284) = 220.
|
||||
|
||||
Evaluate the sum of all the amicable numbers under 10000.
|
||||
"""
|
||||
|
||||
import time
|
||||
|
||||
|
||||
def timer(func):
|
||||
def wrapper(*args, **kwargs):
|
||||
start_time = time.time()
|
||||
result = func(*args, **kwargs)
|
||||
end_time = time.time()
|
||||
print(f"{func.__name__} took {end_time - start_time:.8f} seconds")
|
||||
return result
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
def sieve_primes(limit):
|
||||
"""埃拉托斯特尼筛法生成质数列表"""
|
||||
is_prime = [True] * (limit + 1)
|
||||
is_prime[0:2] = [False, False]
|
||||
primes = []
|
||||
for i in range(2, limit + 1):
|
||||
if is_prime[i]:
|
||||
primes.append(i)
|
||||
for j in range(i * i, limit + 1, i):
|
||||
is_prime[j] = False
|
||||
return primes
|
||||
|
||||
|
||||
def prime_factors_with_sieve(n, primes):
|
||||
"""使用预计算的质数列表进行分解"""
|
||||
factors = {}
|
||||
temp = n
|
||||
for p in primes:
|
||||
if p * p > temp:
|
||||
break
|
||||
while temp % p == 0:
|
||||
factors[p] = factors.get(p, 0) + 1
|
||||
temp //= p
|
||||
if temp > 1:
|
||||
factors[temp] = factors.get(temp, 0) + 1
|
||||
return factors
|
||||
|
||||
|
||||
def get_divisors_optimized(n):
|
||||
"""优化版本:预计算质数加速分解"""
|
||||
if n < 2:
|
||||
return [1] if n == 1 else []
|
||||
|
||||
# 计算需要的质数范围
|
||||
limit = int(n**0.5) + 1
|
||||
primes = sieve_primes(limit)
|
||||
|
||||
# 质因数分解
|
||||
factors = prime_factors_with_sieve(n, primes)
|
||||
|
||||
# 生成除数
|
||||
divisors = [1]
|
||||
for p, exp in factors.items():
|
||||
powers = [p**e for e in range(exp + 1)]
|
||||
divisors = [a * b for a in divisors for b in powers]
|
||||
|
||||
return sorted(divisors)
|
||||
|
||||
|
||||
def sum_of_divisors(n):
|
||||
"""计算一个数的所有真因子之和"""
|
||||
return sum(get_divisors_optimized(n)) - n
|
||||
|
||||
|
||||
def find_amicable_numbers(limit):
|
||||
"""查找小于给定上限的全部亲和数对"""
|
||||
amicable_pairs = set()
|
||||
for a in range(2, limit):
|
||||
b = sum_of_divisors(a)
|
||||
if a != b and sum_of_divisors(b) == a:
|
||||
amicable_pairs.add((min(a, b), max(a, b)))
|
||||
return amicable_pairs
|
||||
|
||||
|
||||
@timer
|
||||
def sum_of_amicable_numbers(limit):
|
||||
"""计算小于给定上限的全部亲和数之和"""
|
||||
return sum(a + b for a, b in find_amicable_numbers(limit))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(sum_of_amicable_numbers(10000))
|
||||
Reference in New Issue
Block a user