寻找涉及指数和除数涉及大数的余数mod

时间:2015-07-04 12:45:43

标签: python algorithm math language-agnostic

我需要一个快速算法来评估以下

((a^n-1)/(a-1)) % p

an几乎相等但少于10 ^ 6而p是一个固定的素数(假设为p=1000003)。我需要在1秒内计算出来。我正在使用python。 Wolfram Mathematica computes it instantly。使用以下代码

需要35.2170000076秒
print (((10**6)**(10**6)-1)/((10**6)-1))%1000003

如果该分母a-1不存在,我可以将权力分组为较小的顺序并使用关系a*b (mod c) = (a (mod c) * b (mod c)) (mod c)但是存在分母。

如何使用快速算法评估此问题?没有numpy / scipy可用。

UPDATE :: 这是我提出的最终代码

def exp_div_mod(a, n, p):
    r = pow(a, n, p*(a-1)) - 1
    r = r - 1 if r == -1 else r
    return r/(a-1)

3 个答案:

答案 0 :(得分:5)

<(>((a ** n)-1)/(a-1))%p

可以改写为

<(>(((a ** n) - 1)%((a-1)* p))/(a-1)

这部分:

<(>((a ** n)-1)%((a-1)* p))

可以通过计算:

来计算

((a ** n)%((a-1)* p))

然后调整为-1。

通过((a-1)* p)将a增加到第n次幂和mod。这可以使用Python pow()函数完成。然后调整-1并除以a-1。

使用pow()函数并传递模数值比计算完整指数然后取模数更快,因为模数可以应用于计算的每个阶段的部分乘积,从而阻止值得到太大(10 6 到10 6 的幂有600万个十进制数字,每一步都应用一个模数值,这些数值永远不会超过modulo - 在这个例子中大约13位数。)

代码:

def exp_div_mod(a, n, p):
    m = p * (a - 1)
    return ((pow(a, n, m) - 1) % m) // (a - 1);

print exp_div_mod((10**6), (10**6), 1000003)

输出:

444446

注意:此方法仅在a,n和p为整数时有效。

答案 1 :(得分:3)

a n -1)/( a -1)是来自的总和我 = 0到 n -1 a i

根据以下内容计算后一个mod p 非常简单:

F a n )为Σ( i = 0 .. n -1 ){ a i }如果 n &gt; 0,否则为0。

现在:

  1. F a n )= a × F a n -1)+ 1

  2. F a ,2 n )=( a +1)×˚F 2 ,n)的

  3. 第二个身份是分而治之的递归。

    由于这两者都只涉及加法和乘法,我们可以计算它们mod p 而不需要大于 a × p 的整数类型通过分配模数运算。 (见下面的代码。)

    只有第一次递归,我们就可以编写迭代解决方案:

    def sum_of_powers(a, n, p):
      sum = 0
      for i in range(n): sum = (a * sum + 1) % p
      return sum
    

    使用分而治之的递归,我们得出的东西并不复杂:

    def sum_of_powers(a, n, p):
      if n % 2 == 1:
        return (a * sum_of_powers(a, n-1, p) + 1) % p
      elif n > 0:
        return ((a + 1) * sum_of_powers(a * a % p, n // 2, p)) % p
      else:
        return 0
    

    第一个解决方案在不到一秒的时间内返回,其中n == 10 6 。第二个即时返回,即使n大到10 9

答案 2 :(得分:2)

您可以乘以import Firebase from 'firebase';的{​​{3}}。由于费马的小定理,对于所有 x p-2 ·x≡x p-1 ≡1(mod p) > 0&lt; x&lt; p ,所以你甚至不需要扩展的Euclid来计算逆,只需要来自标准Python的p - 1函数:

pow

该算法具有时间复杂度(log p),因为使用了modular inverse