当前位置:  开发笔记 > 编程语言 > 正文

我可以降低这个的计算复杂度吗?

如何解决《我可以降低这个的计算复杂度吗?》经验,为你挑选了2个好方法。

好吧,我有一些代码正在大大减慢程序,因为它是线性复杂性,但很多时候都会使程序二次复杂化.如果可能的话,我想降低其计算复杂度,否则我会尽可能地优化它.到目前为止,我已减少到:

def table(n):
    a = 1
    while 2*a <= n:
      if (-a*a)%n == 1: return a

      a += 1

有人看到我错过的任何东西吗?谢谢!

编辑:我忘了提及:n始终是素数.

编辑2:这是我的新改进计划(感谢所有的贡献!):

def table(n):
    if n == 2: return 1
    if n%4 != 1: return

    a1 = n-1
    for a in range(1, n//2+1):
        if (a*a)%n == a1: return a

编辑3:在真实环境中测试它更快!那么这个问题似乎已经解决,但有很多有用的答案.我还应该说,除了上面那些优化之外,我还使用Python词典记忆了这个函数......



1> Konrad Rudol..:

暂时忽略算法(是的,我知道,坏主意),只需切换到,就可以大大减少运行时间.whilefor

for a in range(1, n / 2 + 1)

(希望这不会有一个错误.我很容易做出这些.)

我要尝试的另一件事是查看步长是否可以递增.



2> 小智..:

看看http://modular.fas.harvard.edu/ent/ent_py.如果设置= -1和p = n,则函数sqrtmod可以完成这项工作.

您错过的一个小点是,改进算法的运行时间仍然是n的平方根的顺序.只要你只有小素数n(比如说小于2 ^ 64)就可以了,你应该更喜欢你的实现更复杂的.

如果素数n变大,则可能必须使用一些数论来切换到算法.据我所知,您的问题只能通过时间log(n)^ 3中的概率算法来解决.如果我没记错的话,假设Riemann假设成立(大多数人都这样做),可以证明以下算法的运行时间(在ruby中 - 抱歉,我不知道python)是log(log(n))*的log(n)^ 3:

class Integer
  # calculate b to the power of e modulo self
  def power(b, e)
    raise 'power only defined for integer base' unless b.is_a? Integer
    raise 'power only defined for integer exponent' unless e.is_a? Integer
    raise 'power is implemented only for positive exponent' if e < 0
    return 1 if e.zero?
    x = power(b, e>>1)
    x *= x
    (e & 1).zero? ? x % self : (x*b) % self
  end
  # Fermat test (probabilistic prime number test)
  def prime?(b = 2)
    raise "base must be at least 2 in prime?" if b < 2
    raise "base must be an integer in prime?" unless b.is_a? Integer
    power(b, self >> 1) == 1
  end
  # find square root of -1 modulo prime
  def sqrt_of_minus_one
    return 1 if self == 2
    return false if (self & 3) != 1
    raise 'sqrt_of_minus_one works only for primes' unless prime?
    # now just try all numbers (each succeeds with probability 1/2)
    2.upto(self) do |b|
      e = self >> 1
      e >>= 1 while (e & 1).zero?
      x = power(b, e)
      next if [1, self-1].include? x
      loop do
        y = (x*x) % self
        return x if y == self-1
        raise 'sqrt_of_minus_one works only for primes' if y == 1
        x = y
      end
    end
  end
end

# find a prime
p = loop do
      x = rand(1<<512)
      next if (x & 3) != 1
      break x if x.prime?
    end

puts "%x" % p
puts "%x" % p.sqrt_of_minus_one

缓慢的部分现在找到素数(需要大约log(n)^ 4整数运算); 找到-1的平方根需要512位素数仍然不到一秒.

推荐阅读
云聪京初瑞子_617
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有