题目分析
- 题目给出我们若干数字
- 对于每个数字,从0到当前数字为止,统计其中完全数的个数,输出对应的每一个统计结果
- 完全数的定义为:该数字若所有因子(除去该数字本身)之和为该数字,则该数字为完全数
方法一:统计所有因子
- 实现思路
- 对于给出的数字n,通过
perfectNum
函数判断每一个数字是否为完全数
- 判断的方式是根据完全数的定义来的,对某个数字进行除本身之外的因子统计,如果和为数字本身,则计数一次
- 最终输出统计的结果即可
def perfectNum(n): # 判断是否是完全数
nums = [1] # 1一定是一个因子
i = 2
while i*i <= n: # 尝试因子迭代直到根号n为止
if n % i == 0: # 添加因子到nums组中
nums.append(i)
nums.append(n/i)
i += 1
if sum(nums) == n: # 判断是否符合完全数的规则
return 1
return 0
def count(n): # 统计完全数的个数
res = 0
for i in range(2,n+1):
res += perfectNum(i)
return res
while True:
try:
m = int(input())
print(count(m))
except:
break
复杂度分析
- 时间复杂度:O(∑i=1mni2),对于每一个数字n,都需要n2的时间代价,一重循环的时间开销在统计n以内数字个数的阶段,另一重循环的开销在对于数字本事是否为完全数的时间开销上
- 空间复杂度:O(n),储存因子的数组空间开销
方法二:公式法
- 实现思路
- 欧拉曾推算出完全数的获得公式:如果p是质数,且2p−1也是质数,那么(2p−1)⋅2p−1便是一个完全数。
- 因此对于一个数i,我们要判断i和2i−1都要是质数才可以确定(2i−1)⋅2i−1
- 统计计数结果即可
def isPrime(n): # 判断是否为素数
i = 2
while i*i <= n: # 对自然数进行遍历,判断是否是n的因子
if n % i == 0:
return False
i += 1
return True
def isPerfect(n):
i = 2
count = 0
while i*i <= n: # 对自然数进行遍历
j = pow(2, i) - 1 # 公式中第二部分的计算
perfectNum = pow(2, i-1) * j # 理论上推导的完全数结果
if perfectNum <= n: # 由于上限是n要添加判断
if isPrime(i) and isPrime(j): # 根据欧拉推导的完全数判别定理进行判断
count += 1 # 统计计数
i += 1
return count
while True:
try:
n = int(input()) # 转化成int类型,否则默认输入类型为str
print(isPerfect(n))
except:
break
复杂度分析
- 时间复杂度:O(∑i=1mni2),对于每一个数字n,都需要n2的时间代价,一重循环的时间开销在遍历n以内的自然数来作为质数判断的待定数上,另一重循环的开销在判断公式中两个条件是否满足上
- 空间复杂度:O(1),没有用额外空间开销