【发布时间】:2016-08-17 02:03:16
【问题描述】:
我正在解决一个问题(这是我之前问过的 this 问题的扩展,可以在 here 找到)要求我计算两个数字之间的数字相乘,然后计算幂:
我的第一个方法很简单:
n0=n+1
n1=n0+1
while n1<=(p-1):
n0=n1%p*n0%p
n1+=1
print p-pow(n0,(p-2),p)
constraints:
1 < P <= 2*10^9 , a prime number
1 <= N <= 2*10^9
Abs(N-P) <= 1000
这里我的代码计算 n( 但是当约束变为
0 < N < 4×10^18
1 < P < 4×10^18, a prime number
Abs(N-P) < 10^4
对于这些限制,我的解决方案很慢,并且超出了时间限制。我搜索了各种改进代码的方法。我发现了一个很棒的算法,它可以在O(loglog nM(nlogn)) 时间计算阶乘,其中M 是两个数字相乘的时间复杂度。
该算法首先计算素数,然后计算 n 中素数的指数!然后最后将它们全部相乘(您可以在 here 上看到更多信息)。但是如果我在我的问题中实现这个解决方案,我认为它不会有帮助,因为约束太大而无法在相当长的时间内计算所有素数本身,我只需要找到最多10**4 连续数字的乘法。于是我放弃了这个想法,转而寻找乘法。
我发现 python 乘法速度足够快,它使用“Karatsuba 算法”,实现 Schönhage–Strassen 算法是不明智的(因为我首先想到的是实现这个) 除非至少有 10,000 位数字(因为只有它才能执行 karatsuba)。
而且内置的pow() 也非常快(this file 的第 1426 行显示了实现 math.pow 的 Python 代码,但基本上归结为它调用了可能具有高度优化版本的标准 C 库该函数的)来计算我的约束范围内的幂。
现在我想不出任何其他方法来提高我的代码的时间复杂度。关于时间限制,有人可以帮我找到优化或完全不同且更好的解决方案吗?
我正在解决的问题是here。
【问题讨论】:
-
当我看到“数字太大”和“乘法”时,我会想到对数变换。
-
@muraveill 为什么你删除了你的帖子我刚看到它(我出去了一段时间)它消失了?
-
因为错了。
-
现在再次考虑对数,如果数字太大,也许可以使用斯特林公式来近似阶乘,因为在这种情况下,近似值会很好。
-
你确定是这个在你的代码中花费了太长时间吗?您提到的大小的数字的 1000 次乘法(模 p)几乎不需要时间。