python基础(完数的判断)

 题目描述:

一个数如果恰好等于不包含它本身所有因子之和,这个数就称为"完数"。 例如,6的因子为1、2、3,而6=1+2+3,因此6是"完数"。 编程序找出N之内的所有完数,并按下面格式输出其因子

输入格式:

N

输出格式:

? its factors are ? ? ?

样例输入:
1000
样例输出:
6 its factors are 1 2 3 
28 its factors are 1 2 4 7 14 
496 its factors are 1 2 4 8 16 31 62 124 248 

代码思路:

我的想法是用遍历来求因数,如何在输出。可奈何他的超时了,时间复杂度为o(n**2)

def ys(n):
    ys_list = []
    for i in range(1,int(n/2)+1):
        if n % i == 0:
            ys_list.append(i)
    return ys_list
    
def list_print(ys_list):
    print(*ys_list,end=' ')
    print()

N = int(input())
for i in range(3,N+1):
    ys_list = ys(i)
    sn = sum(ys_list)
    if sn == i:
        print(i,'its factors are',end=' ')
        list_print(ys_list)

 想了想决定在找因数(ys()函数)方面动手:

def ys(n):
    ys_list = [1]
    c = int(n**0.5) + 1
    for j in range(2, c):
        if n % j == 0:
            ys_list.append(j)
            if j != n // j:  # 避免重复添加平方根的因子
                ys_list.append(n // j)
    ys_list.sort()
    return ys_list

从n/2变成了n**2降低了时间复杂度

通过gpt得知了筛选法(Sieve of Eratosthenes)(先求和判断,再求因数)

完全数是满足其所有因子(除了自身)之和等于本身的数。我们可以利用筛选法来排除非完全数,从而减少计算量。

def find_perfect_numbers(N):
    is_perfect = [False] * (N + 1)
    for i in range(2, N + 1):
        if not is_perfect[i]:
            sum_factors = 1
            j = 2
            while j * j <= i:
                if i % j == 0:
                    sum_factors += j
                    if j * j != i:
                        sum_factors += i // j
                j += 1
            if sum_factors == i:
                is_perfect[i] = True
                print(i, 'its factors are', end=' ')
                print_factors(i)

def print_factors(n):
    factors = []
    for i in range(1, int(n/2) + 1):
        if n % i == 0:
            factors.append(i)
    print(*factors, end=' ')
    print()

N = int(input())
find_perfect_numbers(N)

在这个改进后的代码中,我们使用了一个布尔型的列表 is_perfect 来记录每个数是否是完全数。当遍历到某个数 i 时,如果它不是完全数,则对其进行因子求和计算,然后标记为完全数。

在计算因子和时,我们只需要迭代到 sqrt(i),而不是 n/2。这是因为大于 sqrt(i) 的因子可以通过小于 sqrt(i) 的因子来计算得出。

这种算法的时间复杂度主要由 find_perfect_numbers() 函数中的嵌套循环决定,即约为 O(N log(log N)),其中 N 是输入的整数。

总结:

因数的一些查找方法

  1. 暴力遍历法:

    • 方法:从 1 遍历到 n 的一半,检查每个数是否是 n 的因子。
    • 时间复杂度:O(n)
  2. 利用数学特性优化法:

    • 方法:从 1 遍历到 sqrt(n),检查每个数是否是 n 的因子,并利用对称性同时找到另一半的因子。
    • 时间复杂度:O(sqrt(n))
  3. 分解质因数法:

    • 方法:通过不断地除以最小质因数,将一个数分解为质数的乘积,进而找到因数。
    • 时间复杂度:取决于最小质因数的大小,但通常可以近似为 O(log n)
  4. 素数筛法:

    • 方法:使用埃拉托斯特尼筛法等方法预先计算出一定范围内的所有质数,然后通过组合这些质数得出所有因数。
    • 时间复杂度:O(n log log n)(埃拉托斯特尼筛法)

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值