我一直在尝试确定一种用于计算gcd((a ^ n + b ^ n),abs(a-b))的较短方法。我注意到,如果我要计算(使用上述公式),则说a = 100和b = 4,从1开始到n结束(一个循环),在某个点上,答案变为常数。对于a = 100,b = 4和n = 100,我创建了一个从1到n的循环,并在每个点上应用公式,第一个答案(n = 1)为8,之后为32,直到n变为100。为了进行优化,一旦找到两个相等的连续数字,并且最新的数字(此处为32),我就会跳出循环。有谁知道一个简单的公式来计算gcd((a ^ n + b ^ n),a-b),或者更好的是,我主要关心的是一个用于找到(a ^ n + b ^ n)的全局公式
注意: 1. 1 <= a,b,n <= 10 ^ 12
(a ^ n-b ^ n)可以简化为https://math.stackexchange.com/questions/406703/how-to-simplify-an-bn。但是找不到(a ^ n + b ^ n)的版本
在罗里·道顿(Rory Daulton)的哀悼之后,我在函数中实现了下面所示的平方求幂
上述解释的Python套件如下:
a, b, n = map(int, raw_input().split()); ans = -1
if a == b:
ans = (a**n) + (b**n)
else:
for j in xrange(n):
x = gcd((a**n)+(b**n),abs(a-b))
if x != ans:
ans = x
else:
break
print ans
def pow3(x, n):
r = 1
while n:
if n % 2 == 1:
r *= x
n -= 1
x *= x
n /= 2
return r
答案 0 :(得分:2)
我看到两种加快代码速度的方法。
首先,使用数学事实
gcd(r, s) = gcd(r % s, s)
(如果s
不为零)。因此,您无需完全计算a**n + b**n
,只需要对a - b
取模即可。然后,您可以找到(a**n) % (a-b)
和(b**n) % (a-b)
,然后将它们取模a - b
,然后添加它们。
现在,通过exponentiation by squaring method查找a**n
。这涉及一个执行log2(n)
次的循环。在循环的每次遍历中,取余数a - b
来保持数字较小并加快计算速度。
所以有您的算法。在每个步骤中通过平方和模取幂,求出(a**n) % (a-b)
和(b**n) % (a-b)
。然后添加它们并再次取模数。最后,使用a - b
查找该值的GCD。
在某些情况下,例如a - b
素数,我可以看到一些快捷方式。正如您所指出的,数的幂的模数确实会重复。然而,对于大的a - b
来说,找出它们何时重复是一个不平凡的问题,尤其是如果a - b
是复合的并且难以分解的话。除非您有关于a - b
的值和其他参数的其他信息,否则建议您不要使用重复。如果a
和b
的值很小并且事先已知(例如在您的a = 100
和b = 4
的示例中,则重复更具吸引力,您可以预先计算)幂模数96
的值。
您可能应该使用Python的内置pow函数,而不是使用此代码。 See here作为文档。提示@DSM。
根据要求,这是我的求模例程,通过对给定数取平方来求平方。当然,可以进行一些更改。此版本不对参数进行错误检查,并进行了一些小改动以提高效率。
def exp_by_squaring_mod(x, n, mod):
"""Calculate x**n % mod by squaring. This assumes x and n are non-
negative integers and mod is a positive integer. This returns 1 for
0**0.
"""
result = 1
x %= mod
# Reduce n and keep constant the value of result * x**n % mod
while n: # while n is not zero
if n & 1: # n is odd
result = result * x % mod
x = x * x % mod
n >>= 1 # integer divide by 2
return result
答案 1 :(得分:0)
尝试使用这种方法来优化您的幂运算:
def powerBySquaring(x,n):
if n < 0:
x = 1 / x
n = -n
if n == 0: return 1
y = 1
while n > 1:
if n % 2 == 0:
x = x * x
n = n / 2
else:
y = x * y
x = x * x
n = (n-1)/2
return x * y