小编典典

快速计算n!mod m m是素数?

algorithm

我很好奇是否有一个很好的方法可以做到这一点。我当前的代码是这样的:

def factorialMod(n, modulus):
    ans=1
    for i in range(1,n+1):
        ans = ans * i % modulus    
    return ans % modulus

但是似乎很慢!

我也无法计算n!然后应用素数模数,因为有时n太大以至于n!只是显式地计算是不可行的。

我还遇到了http://en.wikipedia.org/wiki/Stirling%27s_approximation,想知道是否可以在某种程度上使用它?

或者,如何在C ++中创建一个递归的,记忆化的函数?


阅读 245

收藏
2020-07-28

共1个答案

小编典典

将我的评论扩展为答案:

是的,有更有效的方法可以做到这一点。 但是它们非常混乱。

因此,除非您确实需要额外的性能,否则我建议您不要尝试实现这些性能。


关键是要注意,模数(本质上是除法)将成为瓶颈操作。幸运的是,有一些非常快速的算法可以让您多次执行相同次数的模数。

这些方法之所以快速,是因为它们基本上消除了模量。


单独使用这些方法应该可以使您获得适度的加速。为了真正有效,您可能需要展开循环以实现更好的IPC:

像这样:

ans0 = 1
ans1 = 1
for i in range(1,(n+1) / 2):
    ans0 = ans0 * (2*i + 0) % modulus    
    ans1 = ans1 * (2*i + 1) % modulus

return ans0 * ans1 % modulus

但要考虑到奇数次的迭代,并将其与我上面链接的一种方法结合起来。

有人可能会认为循环展开应该留给编译器。我会反驳说,编译器目前还不够智能,无法展开这个特定的循环。仔细看看,您会明白为什么。


请注意,尽管我的回答与语言无关,但主要是针对C或C ++的。

2020-07-28