Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/376.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 有效地计算大n的nCr(n,m)mod k_Java_Performance_Dynamic Programming_Number Theory - Fatal编程技术网

Java 有效地计算大n的nCr(n,m)mod k

Java 有效地计算大n的nCr(n,m)mod k,java,performance,dynamic-programming,number-theory,Java,Performance,Dynamic Programming,Number Theory,我需要计算大型n(n)的nCr(n,m)%k,因为nPr有一个明确的公式nPr(n,m)=n!/((n-m)!),你应该尝试使用它。我的建议是: 记住n!=n*(n-1)*…*2*1 请注意,while循环(是的,循环,而不是递归^^^)可以极大地优化计算(除法消除了许多因子,留下一个乘法nPr(n,m)=n*(n-1)*…*(n-m+2)*(n-m+1)) 最后,应在计算nPr(n,m)后计算模,以避免冗余模运算 如果有帮助的话,您可以尝试公式化,这是一个对于n和m的所有有效值都应该为真的

我需要计算大型
n
n)的
nCr(n,m)%k
,因为nPr有一个明确的公式
nPr(n,m)=n!/((n-m)!)
,你应该尝试使用它。我的建议是:

  • 记住n!=n*(n-1)*…*2*1
  • 请注意,while循环(是的,循环,而不是递归^^^)可以极大地优化计算(除法消除了许多因子,留下一个乘法
    nPr(n,m)=n*(n-1)*…*(n-m+2)*(n-m+1)
最后,应在计算nPr(n,m)后计算模,以避免冗余模运算

如果有帮助的话,您可以尝试公式化,这是一个对于
n
m
的所有有效值都应该为真的语句

希望这有帮助:)

编辑
在我写下答案后,我意识到你说的是nCr。对于nCr,您可以在计算nPr后添加另一个while循环,它只计算
m,将nPr除以
m,然后对该答案进行模运算。总之,这将产生一个O(n)算法,它是相当可伸缩的。它使用的内存也非常少。

这在编程竞赛中时不时出现,解决这一问题的一种常见方法是使用Lucas和中国剩余定理


@DAle发布了一个有用的资源,其中有详细信息:

你不是几分钟前就发布了这个问题吗?前一个问题并不精确,它明确地询问了关于记忆的问题,而这里的情况并非如此,相反,我要求输入信息,以有效地解决计算
nPr(n,m)%k
这一更普遍的问题(不一定是备忘录,很可能不会)。有一件事可能会节省一些内存使用量,那就是将
k
外部化,因为它不会在递归过程中发生变异。这将节省内存,因为在您的情况下,您无法利用尾部递归。因此,每次它递归时,它都会保留每次保存3个新
int
s的所有堆栈帧。它保存这些帧il返回。如此有效地,外部化
k
将减少约1/3的内存使用。@CraigR8806好的一点,我更关心的是运行时tho。对于nPr和nCr的事情,很抱歉,对于您的方法,它对于大输入来说效率太低。中国剩余定理()我怀疑这就是我要找的。我目前正试图弄清楚我到底需要如何使用它。@AnnaVopureta算法怎么效率太低了?你可以在开始乘法之前做所有的消去运算。然后做乘法mod n。很抱歉反应太晚了。我不认为中国剩余定理是你可以理解的你在寻找一个O(1)算法吗?代价是计算n!。如果你能找到一种用O(1)计算的方法,那么结果也将是O(1)。否则,您将不得不完全重新考虑这一点,并放弃使用nCr的定义。也许有一个数学定理适合你的需要?希望这有帮助:)@Simon Sirak问题可以通过分解k来解决,然后通过应用Lucas定理将k替换为每个找到的因子来解决问题,然后通过应用CRT将结果组合在一起。DAle提供了更详细的描述:@Henry即使在取消之后,乘法对于大输入来说也太昂贵了。
int choose(int n, int m, int k) {
  if (n==m || m==0)
    return 1 % k;

  return (choose(n-1, m-1, k) + choose(n-1, m , k)) % k;
}