确定友好数字(友好对)的算法
我们正在考虑实现一种算法,用于搜索高达给定限制的友好数字对。
导言
什么是友好号码?
友好数字是两个自然数,使得一个数字的适当除数的总和等于另一个数字,反之亦然。 例如,一对夫妇 它很友好:
\是它自己的除数的总和
\是它自己的除数的总和
让我们开发一个算法,找到所有这些对达到指定的限制。
主要部分
在使用外部软件包之前,您需要安装它。:
import Pkg; Pkg.add("Primes")
连接必要的库:
using Primes, Printf # 用于检查数字的素数,用于格式化输出的Printf
计算素数乘数贡献的函数
此函数计算素数的幂的总和。 从度 以前 .
function pcontrib(p::Int64, a::Int64)
n = one(p) # 我们从p^0=1开始
pcon = one(p) # 用值1初始化和(p^0)
for i in 1:a # 从1到a的每个学位
n *= p # 增加p:p^i的功率
pcon += n # 加p^i的总和
end
return pcon # 我们返回金额:1+p+p^2+。.. +p^a
end
函数操作说明 pcontrib:
要计算一个数字的所有除数的总和,必须考虑到如果数字具有规范分解 ,那么它的所有除数的总和将等于产品:
功能 pcontrib 为特定素因子计算一个这样的括号。
计算所有除数之和的函数
使用其素因式分解计算数的所有除数的总和。
function divisorsum(n::Int64)
dsum = one(n) # 积的初始值为1
for (p, a) in factor(n) # 对于n的展开中度a的每个素因子p
dsum *= pcontrib(p, a) # 乘以总和(1+p+p^2+。.. +p^a)
end
dsum -= n # 我们减去数字本身得到的总和只有它自己的除数。
end
功能说明 divisorsum:
使用算术的基本定理-每个自然数都可以表示为质数幂的乘积(规范分解)。 通过系数的乘积计算所有除数的总和 pcontrib. 然后从这个数量中减去数字本身。 以获得仅其自身除数的总和(小于数字本身)。
寻找友好夫妇的主要功能
主要功能,搜索所有对友好的数字达到极限。
function amicables(L = 2*10^7) # 搜索最大值为L的对(默认值为2000万)
acnt = 0 # 找到的对的计数器
# 信息消息输出
println("Amicable pairs not greater than ", L)
# 我们遍历从2到L的所有数字
for i in 2:L
!isprime(i) || continue # 跳过素数(他们有自己的除数的总和总是1)
j = divisorsum(i) # 计算数字i的适当除数的总和
# 检查友好情况:
# -j必须小于i(以免重演)
# -j的适当除数之和必须等于i
j < i && divisorsum(j) == i || continue
# 如果找到一对,我们增加计数器并输出结果。
acnt += 1
println(@sprintf("%4d", acnt), " => ", j, ", ", i)
end
end
函数中优化的解释 amicables:
循环从 以前 按升序排列。
支票 确保每对只找到一次,即如果一对已经见过面。 然后它将不再输出为 . 素数也被跳过,因为素数的适当除数的总和是 ,而 永远无法形成友好的一对。
amicables() # 使用默认参数开始搜索(最多20,000,000)
程序的结果将包含一个升序排列的友好数字对列表,其中第一个数字小于第二个。
输出格式: <порядковый_номер> => <меньшее_число>, <большее_число>
结论
我们回顾了友好数字搜索算法在Julia编程语言中的实现。
该算法利用将数字分解为素数因子的数学性质来有效地计算它们自己的除数之和。 效率是通过使用数论而不是直接通过所有除数来实现的。 该程序找到所有友好对达到指定的限制,并输出它们与编号。 这种方法在数论和娱乐数学中有实际应用。 有趣的是,古希腊人知道友好的数字,最小的一对(220,284)是毕达哥拉斯发现的。
该示例是使用[Rosetta代码]的材料开发的(https://rosettacode.org/wiki/Amicable_pairs )