【问题标题】:Efficiency in Perfect number code (Python)完美数字代码的效率(Python)
【发布时间】:2021-01-31 07:18:49
【问题描述】:
n = int(input())
sum1 = 0
for i in range(1, n//2  + 1):
    if(n % i == 0):
        sum1 = sum1 + i
if (sum1 == n):
    print("YES")
else:
    print("NO")

这是我在 python 中检查数字是否完美的代码,它提供了正确的输出,但是当我尝试在网站(codechef)上提交它时,我得到了超时。我怎样才能提高效率?

错误是:

状态:超过时间限制

【问题讨论】:

  • 也许你应该在将round(n**(0.5)) 分配给一个变量(比如maxLimit)之后检查直到round(n**(0.5)) 而不是n//2
  • edit 澄清您遇到的错误。包括回溯和整个错误消息。
  • @MisterMiyagi 我收到超出时间限制的错误,因为我猜这不是一个非常有效的代码
  • 没有奇完美数,尝试将它们从循环中删除。
  • 问题标签是什么?

标签: python performance


【解决方案1】:

我在这个问题上也有点挣扎,但我在 leetcode 上解决了here 的问题。我自己能想出的最佳解决方案是这个(适合您的情况):

divs = []
for i in range(1, int(n**0.5 + 1)): 
    if (n % i == 0) and n != i: 
        divs.append(i)
        divs.append(n/i)

print('YES') if sum(divs) - n == n else print('NO')
    

我花了一些时间才到达,但是像 leetcode 这样的网站可以让您非常轻松地测试解决方案,因此您可以尝试不同的方法。此外,您还可以查看解决方案或讨论选项卡,以找到比您现有的更好的答案,以便您改进。

【讨论】:

  • 什么是num
  • 抱歉,将代码编辑为更像给出的示例的剩余部分,将其更改为n。感谢您指出@MisterMiyagi
【解决方案2】:

我写了一个程序来做一个完美的数字测试,其中包括 Lucas Lehmer 测试:

def ffs(x):
    return (x&-x).bit_length()-1

def levelx(N, withstats=False):
  if N <= 1: return False
  temp = N
  newlevel = temp.bit_length()
  primetest = temp//(2**(ffs(temp)))
  offset = temp//primetest
  s = 4
  
  nextlevel = newlevel // 2
  
  check = temp // (2**nextlevel)

  prevtemp = 2**nextlevel

  if withstats == True:
    print (newlevel, newlevel, temp)
    print (newlevel, nextlevel+one, prevtemp)
 
        
  if (prevtemp & (prevtemp-1) == 0) and prevtemp != 0:
       if offset.bit_length() == primetest.bit_length():
          if ((primetest+1) & ((primetest+1)-1) == 0):
             for x in range(primetest.bit_length()-1):
               s = (s * s - 2) % primetest
               if withstats == True:
                  print(s)
               if s in [0,2]: return True
             return False
          else: return False
       else: return False

样本输出:

      
In [8]: for x in range(2,2300): 
   ...:     if levelx((2**(x-1))*(2**x-1)) == True: 
   ...:         print(x) 
   ...:                                                                                                                                                         
2
3
5
7
13
17
19
31
61
89
107
127
521
607
1279
2203
2281    


【讨论】:

    【解决方案3】:

    正如@hivert 指出的那样,下面的解决方案假设完美数是偶数。事实上,不知道是否存在奇完美数,但是有很多信息表明不存在奇完美数。 (https://en.wikipedia.org/wiki/Perfect_number#Odd_perfect_numbers)。

    对于初学者,我们必须有 N > 101500。有了这个,我们将继续处理偶数情况。

    偶数是完美的,如果它具有以下形式:

    2p - 1 * (2p - 1),其中 p 是 Mersenne prime

    我们需要一个方便的质数检查器来有效地执行此操作。幸运的是,这是一个非常流行的话题,并且有很多现有的功能可以做到这一点。例如,@Alexandru 为问题 How to create the most compact mapping n → isprime(n) up to a limit N? 提供的答案是一个非常好的和直接的 python 实现。但是,如果我们追求纯粹的速度,我们将需要采用替代方法,例如米勒拉宾。这是在库中提供的sympy

    这是我们非常高效的完美偶数数检查器:

    from sympy.ntheory import isprime
     
    def IsPerfect(N):
        ## First get the number of 2's that divide N
        ## If there are none, the number is not perfect
     
        p = 0
     
        while N % 2 == 0:
            N = N >> 1
            p += 1
     
        if p == 0:
            return False
     
        q = 2**(p + 1) - 1
     
        if N != q:
            return False
     
        if isprime(N):
            return True
        else:
            return False
    

    这里有一些例子:

    IsPerfect(137438691328)
    True
    
    IsPerfect(33550336)
    True
    
    ## Note 11 is not Mersenne
    2**(11 - 1) * (2**11 - 1)
    2096128
    
    IsPerfect(2096128)
    False
    
    IsPerfect(2658455991569831744654692615953842176) ## instant on my laptop
    True
    

    以下是所有小于 100 的素数:

    mersenne = [2, 3, 5, 7, 13, 17, 19, 31, 61, 89]
    not_mersenne = [11, 23, 29, 37, 41, 43, 47, 53, 59, 67, 71, 73, 79, 83, 97]
    
    [IsPerfect(2**(p - 1) * (2**p - 1)) for p in mersenne]
    [True, True, True, True, True, True, True, True, True, True]
    
    [IsPerfect(2**(p - 1) * (2**p - 1)) for p in not_mersenne]
    [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
    

    【讨论】:

    • 这依赖于没有奇完美数的猜想。它认为它没有得到证实。
    • @hivert,好点子!但是,我们确实知道,如果有一个奇数,它必须大于10^1500...是大于 1500 位。我将编辑我的答案以反映这一点。
    • 提交时它对我有用,谢谢@joseph wood!
    【解决方案4】:

    如果每次找到除数时都添加除数的对应项,则只需扫描直到n 的平方根的数字。 :

    def isPerfect(N):
        return N == (N>1) + sum(d+N//d for d in range(2,int(N**0.5)+1) if N%d==0)
    
    isPerfect(137438691328) # True 
    
    isPerfect(10**14) # False
    

    一种更快的方法是根据数的质因数生成除数:

    def primeFactors(N):
        while not N&1:yield 2;N//=2
        p = 3
        while p*p<=N:
            while not N%p: yield p;N//=p
            p+=2
        if N>1: yield N
    
    def isPerfect(N):
        divisors = {1}
        for p in primeFactors(N):
            divisors.update([d*p for d in divisors])
        return N == sum(divisors)-N
    

    这将允许检查更大的数字(只要它们有足够小的质因数):

    isPerfect(2305843008139952128) # True (0.007 second my laptop)
    
    isPerfect(10**25)              # False (0.002 second)
    
    isPerfect(2658455991569831744654692615953842176) # True (125 seconds)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-25
      • 2017-07-11
      • 2020-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多