我需要一个快速算法来评估以下
((a^n-1)/(a-1)) % p
a
和n
几乎相等但少于10 ^ 6而p
是一个固定的素数(假设为p=1000003
)。我需要在1秒内计算出来。我正在使用python。 Wolfram Mathematica computes it instantly。使用以下代码
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)
答案 0 :(得分:5)
可以改写为
<(>(((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。
现在:
F ( a , n )= a × F ( a , n -1)+ 1
F ( a ,2 n )=( a +1)×˚F(一 2 ,n)的
第二个身份是分而治之的递归。
由于这两者都只涉及加法和乘法,我们可以计算它们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。