记住的ncr递归阶乘问题不适用于大输入

时间:2018-11-15 22:22:15

标签: c++ memoization

我正在尝试使用递归和记事来计算 nck 组合问题。对于少量输入,它运行良好。但是,对于大量输入而言,它是失败的。

  

ans = n! /((n-k)!* k!)

     

对于8C3,答案为56。[有效]

     

对于156C12,预期输出为281014969393251275 [不工作]

我该如何缩放或优化?

单击此处运行代码:http://cpp.sh/9ijiy

#include <iostream>
#include <map>
using namespace std;

long long int calls=0; // I know global vars are bad, but, i'm only using it for checking number of recursive calls

long long int fact(int n)
{
    calls++;
    static map<int, long long int> cache = {{0,1},{1,1}}; // factorial of 0 and 1 is 1

    if(cache.find(n) == cache.end()) // if n is NOT found
    {
        long long int ans = (long long int)n*fact(n-1);
        cache.insert(pair<int, long long int>(n,ans));
    }

    return cache[n];

}
long long int combin(int n, int k)
{
    return fact(n)/(fact(n-k)*fact(k));
}
int main()
{
    calls=0; cout << "8C3 is " << combin(8,6) << endl;
    cout << "Number of calls is " << calls << endl;

    calls=0; cout << "156C12 is " << combin(156,12) << endl;
    cout << "Number of calls is " << calls << endl;

    return 0;
}

1 个答案:

答案 0 :(得分:0)

好吧,因为您有156个!沿途,这是276位数字长(根据google),它肯定不适合任何默认的c ++数据类型。我能想到的唯一解决方案是实现其他一些扩展的方式来存储和处理非常大的数字。首先想到的是实现列乘法(小学那年),并使用字符串(而不是long long)将中间值存储在缓存中。效率不高(编写起来特别令人愉悦),但是由于字符串可以无限长地保存(不是真的,但足够好)长序列的字符,所以可以这样做。