- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
方法一:
C(n,r) = n!/(n-r)!r!
方法二:
在书Combinatorial Algorithms by wilf ,我发现了这个:
C(n,r) 可以写成C(n-1,r) + C(n-1,r-1)
。
例如
C(7,4) = C(6,4) + C(6,3)
= C(5,4) + C(5,3) + C(5,3) + C(5,2)
. .
. .
. .
. .
After solving
= C(4,4) + C(4,1) + 3*C(3,3) + 3*C(3,1) + 6*C(2,1) + 6*C(2,2)
如您所见,最终的解决方案不需要任何乘法。在每个形式 C(n,r) 中,n==r 或 r==1。
这是我实现的示例代码:
int foo(int n,int r)
{
if(n==r) return 1;
if(r==1) return n;
return foo(n-1,r) + foo(n-1,r-1);
}
参见 output在这里。
在方法 2 中,存在重叠的子问题,我们调用递归再次解决相同的子问题。我们可以使用 Dynamic Programming 来避免它.
我想知道哪种计算 C(n,r) 的方法更好?。
最佳答案
这两种方法都会节省时间,但第一种很容易出现 integer overflow .
方法一:
这种方法将在最短的时间内生成结果(最多 n/2
次迭代),并且可以通过小心地进行乘法来减少溢出的可能性:
long long C(int n, int r) {
if(r > n - r) r = n - r; // because C(n, r) == C(n, n - r)
long long ans = 1;
int i;
for(i = 1; i <= r; i++) {
ans *= n - r + i;
ans /= i;
}
return ans;
}
此代码将从较小的一端开始计算分子的乘法,并且由于任何 k
连续整数的乘积可以被 k!
整除,因此不会被整除问题。但是溢出的可能性仍然存在,另一个有用的技巧可能是在进行乘法和除法(和 仍然可能会发生溢出)。
方法 2:
在这种方法中,您实际上是在构建 Pascal's Triangle .动态方法比递归方法快得多(第一个是 O(n^2)
而另一个是指数)。但是,您还需要使用 O(n^2)
内存。
# define MAX 100 // assuming we need first 100 rows
long long triangle[MAX + 1][MAX + 1];
void makeTriangle() {
int i, j;
// initialize the first row
triangle[0][0] = 1; // C(0, 0) = 1
for(i = 1; i < MAX; i++) {
triangle[i][0] = 1; // C(i, 0) = 1
for(j = 1; j <= i; j++) {
triangle[i][j] = triangle[i - 1][j - 1] + triangle[i - 1][j];
}
}
}
long long C(int n, int r) {
return triangle[n][r];
}
然后你可以在 O(1)
时间内查找任何 C(n, r)
。
如果您需要特定的C(n, r)
(即不需要整个三角形),那么内存消耗可以O(n)
从上到下覆盖三角形的同一行。
# define MAX 100
long long row[MAX + 1];
int C(int n, int r) {
int i, j;
// initialize by the first row
row[0] = 1; // this is the value of C(0, 0)
for(i = 1; i <= n; i++) {
for(j = i; j > 0; j--) {
// from the recurrence C(n, r) = C(n - 1, r - 1) + C(n - 1, r)
row[j] += row[j - 1];
}
}
return row[r];
}
内层循环从末尾开始,简化计算。如果您从索引 0 开始,您将需要另一个变量来存储被覆盖的值。
关于c - 哪种计算 nCr 的方法更好,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11809502/
我怀疑作者是如何得出公式背后的直觉来计算这个问题中的 (m + n -2)C n-1 - https://www.geeksforgeeks.org/count-possible-paths-top-
我们数据库中的一些字符存储在 NCR 中(例如 台 (台))。 我需要能够在 alert 窗口中显示它们,所以我需要将值转换为 JavaScript 可以显示的内容。 我该怎么做? 最佳答案 一个简单
这是从 this similar question 复制的代码的解决方案。为什么comb(100, 50)后失败了?我相信它不应该超过long long的限制。如果确实如此,我不应该期待运行时错误而不
我尝试使用这种关系递归地找到 nCr 的值: nCr = (n - r + 1) / r * nC(r-1) int comb(int n, int r){ if(r == 0) return
我的递归函数在数组中查找 nCr 对象时遇到问题。 这仅在 r=2 时有效,这意味着仅当进入 1 层时。 当 r > 2 时,我的临时 'a' 数组似乎全乱了 // find nCr combinat
我正在尝试查找 nCr 值。没有错误,但我得到 1 作为所有输入的答案。请帮我找到解决方案。 #include int fact(int num) { int f=1,i; for(
我这里有两个函数一起计算 nCr: int factorial(int n) { int c; int result = 1; for (c = 1; c n - r) r = n - r;
我想从输入数组中返回所有可能组合的完整数组。我想生成 n 选 k 组合,其中 k=1 到 n。到目前为止,我一直非常不成功。 static void combinationUtil(String[]
下列递归方程的解是什么? T(n, 0) = 1, T(n, n) = 1, T(n, r) = T(n-1, r-1) + T(n-1, r) + 1 我在尝试找出对函数 nCr 的调用次数时得
方法一: C(n,r) = n!/(n-r)!r! 方法二: 在书Combinatorial Algorithms by wilf ,我发现了这个: C(n,r) 可以写成C(n-1,r) + C(n
请帮帮我。该程序应该递归地找出两个数字的组合。 nCr = n!/(r!(n-r)!)。当我在 GCC 上编译它时,收到此错误消息。 这是终端显示的内容: 输入两个数字:84段错误 (程序退出,代码:
我想使用 Java 解码从网站的 HTTP GET 请求中获得的以下字符串: Ö ' ü (我实际上必须将它们放入代码博客中,Stackoverflow 会自动解码它们,我希望我能尽快做到这一点;))
我在下面编写了代码来计算 n 个 testCount 值的 nCr。它似乎适合我的值(value)观,但 hacker earth 的测试用例失败,问题链接 http://www.hackereart
我正在尝试使用 dp 在 c 中计算 ncr(组合)。但它在 n=70 时失败了。谁能帮忙? unsigned long long ncr( int n , int r) { unsigned lon
您好,我在代码 sprint5 问题中实现 nCr MODm 时遇到了问题。问题链接是…… https://www.hackerrank.com/contests/codesprint5/challe
我试图解决一个涉及大阶乘模质数的问题,并在另一个人的解决方案中发现了以下算法: long long factMod (long long n, long long p) { long long
更新:组合数学和排序最终是我所需要的。下面的链接帮助很大: http://msdn.microsoft.com/en-us/library/aa289166(v=vs.71).aspx http://
我正在为本地语言制作一个提要阅读器应用程序。新闻网站提供带有这些字符的 RSS feed ഹലോ സ്റ്റാക്ക്ഓവ x0D7C; ഫ്ലോ 这实际上意味着ഹലോസ്റ്റാക്ക്ഓവ
这个问题已经有答案了: How do I decode HTML entities in Swift? (23 个回答) 已关闭 5 年前。 如何转换这种类型的十六进制字符串 🚗 表情
我为自己创建了一个关于如何执行 nCr % 1000000007 的函数。 我需要真正找到 (nCr + n2Cr2 + n3Cr3 +...) % 1000000007 我该如何从这里开始 (nCr
我是一名优秀的程序员,十分优秀!