如何使完美的功率算法更有效?

时间:2016-08-28 11:32:02

标签: python algorithm python-3.x

我有以下代码:

def isPP(n):
  pos = [int(i) for i in range(n+1)]
  pos = pos[2:] ##to ignore the trivial n** 1 == n case
  y = []
  for i in pos:
      for it in pos:
          if i** it == n:
              y.append((i,it))
              #return list((i,it))
      #break
  if len(y) <1:
      return None
  else:
      return list(y[0])

直到〜2000年才能完美运行,因为我在内存中存储的太多了。我该怎么做才能使它有效地用于大数(例如,50000或100000)。我找到一个案例后试图让它结束,但如果数字很大,我的算法效率仍然太低。

任何提示?

5 个答案:

答案 0 :(得分:5)

IIRC,它可以更容易地进行迭代检查&#34;它是否有平方根?它有立方根吗?它有第四个根吗? ...&#34;您将很快到达假定根必须位于12之间的点,此时您可以停止。

答案 1 :(得分:4)

如果存在 b e b ^ <,则数字 n 是完美的力量em> e = n 。例如216 = 6 ^ 3 = 2 ^ 3 * 3 ^ 3是完美的幂,但是72 = 2 ^ 3 * 3 ^ 2不是。

确定数字是否为完美幂的技巧是要知道,如果数字是一个完美的幂,则指数 e 必须小于log2 n ,因为如果 e 大于2 ^ e 将大于 n 。此外,只需要测试素数 e ,因为如果数字是复合指数的完美幂,它也将是复合分量的素因子的完美幂;例如,2 ^ 15 = 32768 = 32 ^ 3 = 8 ^ 5是一个完美的立方根,也是一个完美的第五根。

下面显示的函数isPerfectPower通过首先使用Newton方法计算整数根来测试每个素数小于log2 n ,然后为结果提供电源以检查它是否相等到 n 。辅助函数primes通过Eratosthenes的Sieve计算素数列表,iroot通过Newton方法计算整数 k th-root,并{{1通过二进制搜索计算整数对数到 b

ilog

my blog处进一步讨论了完美的权力谓词。

答案 2 :(得分:0)

试试这个牛顿方法:

def NthRoot(k, num):
    i, j = num, num+1
    while i < j:
        j = i
        t = (k-1) * j + num // pow(j, k-1)
        i = t // k
    return j

print(NthRoot(3,125))

https://en.wikipedia.org/wiki/Newton's_method

答案 3 :(得分:0)

相关改进将是:

import math

def isPP(n):

        # first have a look at the length of n in binary representation
        ln = int(math.log(n)/math.log(2)) + 1

        y = []
        for i in range(n+1):
                if (i <= 1):
                        continue
                # calculate max power

                li = int(math.log(i)/math.log(2))
                mxi = ln / li + 1
                for it in range(mxi):
                        if (it <= 1):
                                continue
                        if i ** it == n:
                                y.append((i,it))
                                # break if you only need 1

        if len(y) <1:
                return None
        else:
                return list(y[0])

答案 4 :(得分:0)

我认为更好的方法是实施这种“黑客”:

$all_users = array(); // intialzie array

while ($usuario = mysqli_fetch_array($resultado, MYSQLI_ASSOC)) {

    $usermail = $usuario['email']; 
    $hash = $usuario['hash'];
    mysqli_query($dbc, "UPDATE newsletter SET enviado = '1' WHERE email='$usermail' "); 

    $all_users[] = $usermail; // push all emails first
}

// then send

 try {
    $email->setTos($all_users)
    ->setFrom("no_responder@test.com.ar")
    ->setFromName("test")
    ->setReplyTo("no_responder@test.com.ar")
    ->setSubject("Convocatorias Semanales")
    ->setHtml('<html><body>TEST</body></html>');

    $result = $sendgrid->send($email);
    echo "enviado";

} catch(\SendGrid\Exception $e) {
    echo $e->getCode() . "\n";
    foreach($e->getErrors() as $er) {
        echo $er;
    }
}

结果:

import math

def isPP(n):
    range = math.log(n)/math.log(2)
    range = (int)(range)
    result = []
    for i in xrange(n):
        if(i<=1):
            continue
        exponent = (int)(math.log(n)/math.log(i))
        for j in [exponent-1, exponent, exponent+1]:
            if i ** j == n:
                result.append([i,j])
    return result

print isPP(10000)

黑客使用以下事实:

[[10,4],[100,2]]

由于这个计算在浮点数上可能略微偏离,给出了非常近似的结果,因此将指数检查为if log(a)/log(b) = c, then power(b,c) = a 的准确度。

您可以对+/- 1

等角落案件进行必要的调整