【问题标题】:multiplication of all numbers (between 2 numbers) python所有数字的乘法(2个数字之间)python
【发布时间】: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)几乎不需要时间。

标签: python algorithm exponent


【解决方案1】:

[编辑]Stirling's formula 表示对于大的N,您可以用日志近似N!,对于计算机来说更容易处理的数字:

N! % p =~ exp((N* ln(N) - N)) % p

对于小数,保留阶乘以获得更高的精度。

【讨论】:

    【解决方案2】:

    一个简单的 *2 加速可以来自将代码更改为:

    n0=n+1
    for n1 in range(n0+1,p):
        n0 = (n0 * n1)%p
    return p-pow(n0,(p-2),p) 
    

    每次迭代只进行一次模运算。

    额外的 10 倍加速可以来自预先计算阶乘。 您将乘以从 n+1 到 p-1 的所有值,这与乘以 -1 到 n+1-p 相同。所以你可以预先计算一个数组 A[x] 等于 -1*-2...*-x 的乘积,并使用这个预先计算的值而不是循环。

    (请注意,您需要将此预先计算的数组保持在其完整的整数精度中,因为在预先计算期间您不知道您将使用哪个素数。)

    预计算代码为:

    t=1
    A=[1]
    for y in range(1,10**4+1):
        A.append(t)
        t*=-y
    

    然后对于您计算的每种情况:

    return 0 if n>=p else p-pow(A[p-n]%p,(p-2),p) 
    

    【讨论】:

    • 是的,这就是我要找的东西。非常感谢@Peter de Rivaz 的帮助。你是绝对正确的
    • 您从哪里发现“从 n+1 到 p-1 的所有值,这与乘以 -1 到 n+1-p 相同”。我的意思是是对的,但您是从哪里了解到这个属性的?
    • 我想的是,如果我从每个数字中减去 p 会发生什么。 n+1 变为 n+1-p,p-1 变为 -1。当你在做模 p 的计算时,这显然不会改变结果,现在模式变得很容易发现。
    • 哇!太好了,你想了这么多,有了你的这个想法,我的代码在最短的时间内完成了在线评委。再次感谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-09
    • 1970-01-01
    • 2015-11-13
    • 1970-01-01
    相关资源
    最近更新 更多