前言
在遥远的古代,人们发现某些自然数之间有特殊的关系:如果两个数a和b,a的所有除本身以外的因数之和等于b,b的所有除本身以外的因数之和等于a,则称a,b是一对亲和数。
据说,毕达哥拉斯, 希腊文Πυθαγόρας,约前580年—前500年)的一个门徒向他提出这样一个问题:“我结交朋友时,存在着数的作用吗?”毕达哥拉斯毫不犹豫地回答:“朋友是你的灵魂的倩影,要像220和284一样亲密。”又说“什么叫朋友?就像这两个数,一个是你,另一个是我。”后来,毕氏学派宣传说:人之间讲友谊,数之间也有“相亲相爱”。从此,把220和284叫做“亲和数”或者叫“朋友数”或叫“相亲数”。这就是关于“亲和数”这个名称来源的传说。220和284是人类最早发现,又是最小的一对亲和数。
发现历史
320年左右,古希腊毕达哥拉斯发现的220与284,是人类认识的第一对相亲数。
约850年,阿拉伯数学家塔别脱·本·科拉就发现了相亲数公式,后来称为塔别脱·本·科拉法则。
1636年,费马发现了另一对相亲数:17296和18416。
1638年,笛卡尔也发现了一对相亲数:9363584和9437056。
1747年,年仅39岁的欧拉也研究过相亲数这个课题。1750年,他一口气向公众抛出了60对相亲数:2620和2924,5020和5564,6232和6368,……,从而引起了轰动。
1866年,年方16岁的意大利青年巴格尼尼发现1184与1210是仅仅比220与284稍为大一些的第二对相亲数。
目前,人们已找到了12,000,000多对相亲数。但相亲数是否有无穷多对,相亲数的两个数是否都是或同是奇数,或同是偶数,而没有一奇一偶等,这些问题还有待继续探索。
亲和数的定义
- 如果 a和b是一对亲和数,那么 a的所有真因数之和等于b,且b的所有真因数之和等于a
- 一对亲和数,同为偶数或同为奇数(待推翻,哈哈哈...)
例如,220和284是一对亲和数:
220的真因数:1, 2, 4, 5, 10, 11, 20, 22, 44, 55, 110,它们的和为284。
284的真因数:1, 2, 4, 71, 142,它们的和为220。
欧拉公式
计算亲和数的公式主要有几种,其中最著名的是欧拉公式。
注:欧拉公式生成的亲和数对有限,且不是所有亲和数对都可以通过此公式生成。
代码
- is_prime 函数:用于检查一个数是否为素数。这个函数使用了基本的素数检测算法,对于较小的数效率较高。
- euler_formula 函数:根据欧拉公式生成亲和数对。首先计算 a,b,c,然后检查它们是否都是素数。如果是,计算并返回亲和数对。
- 主循环:从 2到 50调用 euler_formula 函数生成亲和数对,并打印结果。
def is_prime(n):
"""检查一个数是否为素数"""
if n <= 1:
return False
if n <= 3:
return True
if n % 2 == 0 or n % 3 == 0:
return False
i = 5
while i * i <= n:
if n % i == 0 or n % (i + 2) == 0:
return False
i += 6
return True
def euler_formula(x):
"""使用欧拉公式生成亲和数对"""
a = 3 * (2 ** x) - 1
b = 3 * (2 ** (x - 1)) - 1
c = 9 * (2 ** (2 * x - 1)) - 1
if is_prime(a) and is_prime(b) and is_prime(c):
num1 = 2 ** x * a * b
num2 = 2 ** x * c
return (num1, num2)
else:
return None
# 生成一些亲和数对
for x in range(2, 20):
pair = euler_formula(x)
if pair:
print(f"亲和数对: {pair}")
# 亲和数对: (220, 284)
# 亲和数对: (17296, 18416)
# 亲和数对: (9363584, 9437056)
暴力枚举法
直接说结论吧.
所有100万以下的数逐一进行了检验,总共找到了40对亲和数,
发现10万以下数中仅有13对亲和数。
小技巧:通过预计算每个数的真因数之和,然后在查找亲和数对时直接使用这些预计算的值,进一步提高了效率
def sum_of_divisors(n):
"""计算一个数的真因数之和"""
sum_div = 1 # 1 是所有数的真因数
for i in range(2, int(n**0.5) + 1):
if n % i == 0:
sum_div += i
if i != n // i:
sum_div += n // i
return sum_div
def find_amicable_numbers(limit):
"""找到所有小于 limit 的亲和数对"""
amicable_pairs = []
sum_divisors = [1] * limit # 初始化真因数之和数组
for i in range(2, limit):
for j in range(i * 2, limit, i):
sum_divisors[j] += i
for a in range(2, limit):
b = sum_divisors[a]
if b < limit and b > a and sum_divisors[b] == a:
amicable_pairs.append((a, b))
return amicable_pairs
# 示例:找到所有小于 10000 的亲和数对
limit = 1000000
amicable_pairs = find_amicable_numbers(limit)
print(f"小于 {limit} 的亲和数对:{amicable_pairs}")
print(len(amicable_pairs))
总结
亲和数有着漫长的发现历史和美丽动人的传说。从古希腊的毕达哥拉斯学派到中世纪的阿拉伯数学家,再到近代的费马、欧拉等数学大师,都与亲和数的发现和研究有着密切的联系。这些历史故事和传说为亲和数赋予了浓厚的文化底蕴,使其成为数学史上的一段佳话,也让人们在了解亲和数的过程中,领略到数学发展的历史脉络和人类智慧的传承。