鱼C论坛

 找回密码
 立即注册
查看: 1309|回复: 2

[已解决]找出10000以内的**完美数**

[复制链接]
发表于 2020-5-4 16:26:22 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
这道题是我在github上面看到的
2. 找出10000以内的**完美数**。

   > **说明**:完美数又称为完全数或完备数,它的所有的真因子(即除了自身以外的因子)的和(即因子函数)恰好等于它本身。例如:6($6=1+2+3$)和28($28=1+2+4+7+14$)就是完美数。完美数有很多神奇的特性,有兴趣的可以自行了解。
代码如下:
for num in range(1, 10000):
    result = 0
    for factor in range(1, int(num**0.5) + 1):
        if num % factor == 0:
            result += factor
            if factor > 1 and num // factor != factor:
                result += num // factor

    if result == num:
        print(num)
标注颜色的这两行代码不是很理解,是把被num整除并且不是1和num开方的数
最佳答案
2020-5-4 21:16:22
本帖最后由 txxcat 于 2020-5-4 21:38 编辑

首先在不看答案的情况下写了一段代码:
'''Perfect number'''
for i in range(1,10000):
    a=0
    for j in range(1,i//2+1):
        if i%j==0:
            a+=j
    if i==a:
        print(i)
运行起来没问题,再和答案的代码进行了对比,发现虽然我写的简单,但是效率不高,因为除数的范围到了被除数的一半,越往后,运算量越大。
答案的代码就减少了不少,除数范围只有平方根以下的数,减少了不少运算量,为什么这么算,以28为例子来说明:
28的因子有:1、2、4、7、14,除了1可以分为2*14、4*7,可见其实因子数除了1以外都是成对出现的,相乘等于被除数本身,所以找到分界点就行了,然后除以算出来的因子得到对应的另一个因子数。分界点就是平方根,这点好理解吧。后面得到对应因子的判断中,排除1的原因已经直到了,但是为什么num // factor != factor?这是防止平方根正好也是因子的情况,不排除掉就会重复多算了一个因子。
根据这个算法优化了一下代码,
for num in range(2, 10000):         #从2开始算可以避开这个算法的一个小bug
    result = 1                                           #1是所有整数的因子,所以1就不进入循环直接带入可以少算一轮
    for factor in range(2, int(num**0.5) + 1):           #从2开始循环,原代码的1的判断可以去掉了
        if num % factor == 0:
            result += (factor+(num / factor if factor**2!=num else 0 ))     #直接把成对因子加入,平方根是因子就只算1个。
    if result == num:
        print(num)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-5-4 17:50:19 | 显示全部楼层
这种写法的原因是因为第三行的range(1, int(num**0.5) + 1),其实也可以使用range(1,10000)#(后面代码也需要相应做出一些改变),这不过考虑到计算机的执行效率来说,前者更快。#(后者要等很长很长的时间)
用前者解的话,就需要注意因子并非仅仅存在于factor in (1, int(num**0.5) + 1)这个范围内,同时num / factor 所得到的数也有可能是因子,因此有了第7行的 result += num // factor。第六行的判断语句num // factor != factor是防止将因子重新加一次的情况出现。
最后还要说一下,这个代码运行后存在1,但是1不是完数,所以,这个东西我的解决方案是把第一段代码改为for num in range(2, 10000).望采纳。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-4 21:16:22 | 显示全部楼层    本楼为最佳答案   
本帖最后由 txxcat 于 2020-5-4 21:38 编辑

首先在不看答案的情况下写了一段代码:
'''Perfect number'''
for i in range(1,10000):
    a=0
    for j in range(1,i//2+1):
        if i%j==0:
            a+=j
    if i==a:
        print(i)
运行起来没问题,再和答案的代码进行了对比,发现虽然我写的简单,但是效率不高,因为除数的范围到了被除数的一半,越往后,运算量越大。
答案的代码就减少了不少,除数范围只有平方根以下的数,减少了不少运算量,为什么这么算,以28为例子来说明:
28的因子有:1、2、4、7、14,除了1可以分为2*14、4*7,可见其实因子数除了1以外都是成对出现的,相乘等于被除数本身,所以找到分界点就行了,然后除以算出来的因子得到对应的另一个因子数。分界点就是平方根,这点好理解吧。后面得到对应因子的判断中,排除1的原因已经直到了,但是为什么num // factor != factor?这是防止平方根正好也是因子的情况,不排除掉就会重复多算了一个因子。
根据这个算法优化了一下代码,
for num in range(2, 10000):         #从2开始算可以避开这个算法的一个小bug
    result = 1                                           #1是所有整数的因子,所以1就不进入循环直接带入可以少算一轮
    for factor in range(2, int(num**0.5) + 1):           #从2开始循环,原代码的1的判断可以去掉了
        if num % factor == 0:
            result += (factor+(num / factor if factor**2!=num else 0 ))     #直接把成对因子加入,平方根是因子就只算1个。
    if result == num:
        print(num)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-27 02:34

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表