程序地址:http://www.cheemoedu.com/exercise/13
问题描述:
完全数(Perfect number),又称完美数或完备数,是一些特殊的自然数。它所有的真因子(即除了自身以外的约数)的和(即因子函数),恰好等于它本身。例如,第一个完全数是6,它有约数1、2、3、6,除去它本身6外,其余3个数相加,1+2+3=6。第二个完全数是28,它有约数1、2、4、7、14、28,除去它本身28外,其余5个数相加,1+2+4+7+14=28。
编程求10000以内的完全数。
我的代码:
import datetime starttime = datetime.datetime.now() def perfect(n): m=[i for i in range(1,n/2+1) if n%i==0] if sum(m)==n: print n for k in range(1,10000): perfect(k) endtime = datetime.datetime.now() print (endtime - starttime).seconds
我的思路:
首先定义一个求一个数的所有约数的函数(这个函数一定要尽量快速简单,否则计算100内的完全数还行,范围大一点的话就会奇慢无比),然后用for循环遍历即可;
之前淘汰的代码:
def perfect(n): a=[] for i in range(1,n+1): for j in range(n,0,-1): if i*j==n: a.append(i) a.pop() if sum(a)==n: print n for k in xrange(1,10000): perfect(k)
思路其实很简单,实现起来也容易,但是想要很快速的显示完全数却是个不简单的任务,起初,我没觉得难(100以内的秒出),可是范围增大到1000时,速度明显慢了很多,到10000时,等了10几分钟都没反应,后来我进行了优化,根据“完全数都是以6或8结尾(如果以8结尾,那么就肯定是以28结尾)”原理,将范围缩减到了1000多个数,可是还是很慢很慢,后来又根据“除6以外的完全数,它们被3除余1、9除余1、还有1/2被27除余1(百科上看的)”将范围缩减到了120多个,但是还是慢(长达14秒),这才意识到是代码写的有问题,想来想去就写了最上面的那个,它的结果为:
E:\python\python.exe D:/pycharm/python/奇猫百题/完全数.py
6
28
496
8128
6 #运行时间为6秒
虽然计算10000以内的还算可以,但是在增加一个数量级又会很慢,没辙了,这时我所能想到的最快的方法了。
示例代码:
def isPerfectNumber(n): a = 1 b = n s = 0 while a < b: if n % a == 0: s += a + b a += 1 b = n / a if a == b and a * b == n: s += a return s - n == n for k in range(2, 10000): if isPerfectNumber(k): print k
代码分析:
示例代码的while循环是一边算传入数的约数,一边求其和,然后判断是否满足关系,满足的话就多加个a(两个约数相等且积为原数),其次还要减去n(第一次循环时加上了b),最后再返回完全数;
虽然a是递增的,但是b的范围几乎是折半的,而且比较的是a和b的大小,所以它每一个数循环的次数都很少,而且不用再另算总和,所以比我的要快,事实证明,在计算10000以内的完全数时几乎是秒出,而100000时才用了11秒,真的比我的要好很多。