题目描述
完全数(Perfect number),又称完美数或完备数,是一些特殊的自然数。
它所有的真因子(即除了自身以外的约数)的和(即因子函数),恰好等于它本身。
例如:28,它有约数1、2、4、7、14、28,除去它本身28外,其余5个数相加,1+2+4+7+14=28。
输入n,请输出n以内(含n)完全数的个数。
数据范围:
1
≤
n
≤
5
×
1
0
5
1 \le n \le 5 \times 10^5
1≤n≤5×105
输入描述
输入一个数字n
输出描述
输出不超过n的完全数的个数
代码
def is_perfect(number):
L=[]
for i in range(1,number//2+1):
if number%i==0:
L.append(i)
if sum(L)==number:
return 1
else:
return 0
while True:
try:
n=int(input())
k=0
for i in range(3,n+1):
if is_perfect(i)==1:
k+=1
print(k)
except:
break
代码解释
- 找出数number除本身外的所有因子,判断是否为完全数。由于2是除1外的最小应数,故大于number/2的因数(除自身以外)是不存在的,循环到number/2即可
- 由于1,2显然不是完全数,故循环可以从3开始
优化
由于一个数n的因数分布在
n
\sqrt n
n的两侧,故可以减少循环次数到
n
\sqrt n
n
但是需要注意不能把数n本身算在因数列表里
优化后的函数如下。牛客测试用例的运行时间从550ms下降到68ms
def is_perfect(number):
L=[1]
for i in range(2,int(number**0.5)+1):
if number%i==0:
L.append(i)
L.append(number//i)
if sum(L)==number:
return 1
else:
return 0
补充
n最大可输入 5 × 1 0 5 5 \times 10^5 5×105,在牛客运行仍旧超时,因此考虑直接从数学理论入手
完全数公式
完全数公式
由完全数公式可知,对任意一个整数n,若
2
n
−
1
2^n-1
2n−1是质数,则
(
2
n
−
1
)
2
n
−
1
(2^n-1)2^{n-1}
(2n−1)2n−1是一个完全数。
重新看本题,我们可以先写一个判断是否为质数的函数。由于
2
0
−
1
2^0-1
20−1和
2
1
−
1
2^1-1
21−1不是质数,因此在range(2,n+1)进行循环,如果当前循环
(
2
i
−
1
)
2
i
−
1
(2^i-1)2^{i-1}
(2i−1)2i−1在输入的范围内,则计数,否则立刻退出循环。最后输出完全数的数量.
牛客通过全部运行用例的时间下降到44ms,自测输入500000可出结果.
import math as ma
# 判断是否为素数
def is_prime(number):
if number==1:
return False
if number==2:
return True
for i in range(2,int(ma.sqrt(number))+1):
if number%i==0:
return False
return True
while True:
try:
n=int(input())
k=0
for i in range(2,n+1):
if (2**i-1)*pow(2,i-1)<=n:
if is_prime(2**i-1)==True:
k+=1
else:
break
print(k)
except:
break