描述
本题要求实现一个计算整数因子和的简单函数,并利用其实现另一个函数,输出最小的N(1 <= N <=8)个完数。所谓完数就是该数恰好等于除自身外的因子之和。例如:6=1+2+3,其中1、2、3为6的因子。
输入格式
一个正整数N,如:1
输出格式
如:6=1+2+3
找出一个数的所有因子,根据这些因子的和是否与该数相等,判定该数是否是完数
def factor(num): # 寻找 num 的所有因子ls = []for i in range(1, num):if num % i == 0:ls.append(i) # 将num的所有非本身因子加入列表if sum(ls) == num: # 如果num是完数,返回列表,否则返回Falsereturn ls # 返回包含完数所有因子的列表else:return False
找到前n个完数
def oupput(n): # 按格式输出找到的完数count,i = 1,1 # 计数器置1while count <= n: # 只寻找前n个完数if factor(i): # 如果i 是完数,按格式输出print('{}={}'.format(i, '+'.join([str(x) for x in factor(i)])))count = count + 1i = i + 1
完整参考程序为:
def factor(num): # 寻找 num 的所有因子ls = []for i in range(1, num):if num % i == 0:ls.append(i) # 将num的所有非本身因子加入列表if sum(ls) == num: # 如果num是完数,返回列表,否则返回Falsereturn lselse:return Falsedef oupput(n): # 按格式输出找到的完数count,i = 1,1 # 计数器置1while count <= n: # 只寻找前n个完数if factor(i): # 如果i 是完数,按格式输出print('{}={}'.format(i, '+'.join([str(x) for x in factor(i)])))count = count + 1i = i + 1if __name__ == '__main__':n = int(input()) # 此处要求输入为正整数oupput(n) # 调用输出函数
这个题目的计算量比较大,如果想找到更多的完数,需要使用一些算法,例如数学方法 :
6=1+2+3 (22-1)+(22-1)1=2(22-1)
28=1+2+4+7+14 (23-1)+(23-1)*(22-1)=22*(23-1)
496=1+2+4+8+16+31+62+124+248 (25-1)+(25-1)(24-1)=(24)(25-1)
8128=1+2+4+8+16+32+64+127+254+508+1016+2032+4064 (27-1)+(27-1)*(26-1)=(26)*(27-1)
33550336= 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8191, 16382, 32764, 65528, 131056, 262112, 524224, 1048448, 2096896, 4193792, 8387584, 16775168]
如果 m 是素数,且 2 m - 1 也是素数,那么2 (m - 1) (2 * m - 1) 是一个完数。
判断素数的函数 :
def isPrime(n): # 判断素数的函数if n < 2:return False # 0和1不是素数for i in range(2, int(n**0.5)+1):if n % i == 0:return Falseelse:return True
判断完全数的函数:
def isPerfect(m): # 判断完数的函数if isPrime(m) and isPrime(2 * *m - 1): # 如果 m 和 2 ** m - 1 都是素数s = 2 ** (m - 1) * (2 ** m - 1) # 2 ** (m - 1) * (2 ** m - 1) 是一个完数ls.append(s) # 完数加入到列表中i=0while s % 2 ==0: # 对完数进行分解因数s=s // 2factor.append(s) # s // 2 和 2 ** i 次方同时是因子factor.append(2 ** i)# 496=1+2+4+8+16+ 31 +62+124+248i = i + 1if len(factor) % 2 == 0: # 加入最后一个因子 2 ** ifactor.append(2 ** i)return selse:return False
完整参考代码,以下代码可以完成前9个完数的输出:
def isPrime(n): #判断素数的函数if n < 2:return False #0和1不是素数for i in range(2, int(n**0.5)+1):if n % i == 0:return Falseelse:return Truedef isPerfect(m): #判断完数的函数if isPrime(m) and isPrime(2**m-1):s = 2**(m-1)*(2**m-1)ls.append(s)i=0while s%2 ==0:s=s//2factor.append(s)factor.append(2**i)i = i+1if len(factor)%2==0:factor.append(2 ** i)return selse:return Falseif __name__ == '__main__':n = int(input()) # 此处要求输入为正整数ls = []count, num = 0, 1while count < n:factor = []if isPerfect(num):factor.sort()print('{}=1'.format(ls[count]), end='')for j in factor[1:]:print("+{}".format(j), end='')count = count + 1print()num = num + 1
还有一种更高效的方法,可以完成前14个完数的输出:
# 公管大数据1901班康佳丽n = int(input())def isPrime(N):if N < 4: return N > 1if ((N & 1) == 0): return Falsei = 3while i * i <= N :if (N % i) == 0 :return Falsei += 2return Truedef primality(N, M):if N == 2 :return Trues = 4for i in range(0, N - 2) :s = (s * s - 2) % Mreturn s == 0def findPerfectNumber() :count = 0ls=[]for i in range(2, 5000):M = (1 << i) - 1t = M << (i-1)# 当p为素数且梅森数2^p-1为素数时2^(p-1)*(2^p-1)为完全数if isPrime(i) and primality(i,M) :count += 1ls.append(t)if count>n-1:return(ls)Lis=findPerfectNumber() # 得到包含前n位完数的列表def Yinzi(s): # 获取每个完数的因子i=0while s%2 ==0:s=s//2factor.append(s)factor.append(2**i)i = i+1if len(factor)%2==0:factor.append(2 ** i)return factorcount = 0ls = []for i in Lis:factor=[]factor = Yinzi(i)factor.sort()print('{}=1'.format(Lis[count]), end='')for j in factor[1:]:print("+{}".format(j), end='')count = count + 1print()
