【问题标题】:Memoized ncr recursive factorial problem not working for large inputs记忆化的 ncr 递归阶乘问题不适用于大输入
【发布时间】:2018-11-15 22:22:15
【问题描述】:

我正在尝试使用递归和记忆来计算 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;
}

【问题讨论】:

    标签: c++ memoization


    【解决方案1】:

    好吧,既然你有 156 个!一路上,它有 276 位长(根据谷歌),它肯定不适合任何默认的 c++ 数据类型。我能想到的唯一解决方案是实现一些其他的扩展方式来存储和操作非常大的数字。首先想到的是实现列乘法(小学的东西)并使用字符串(而不是 long long)将中间值存储在缓存中。它不会很有效(编码特别愉快),但由于字符串可以无限地保存(不是真的,但足够好)长字符序列,所以可以这样做。

    【讨论】:

    • 更好的解决方案是重新考虑combin 的工作方式,以避免计算大量的阶乘。
    • 是的,这就是我需要帮助的地方。我机器上 long long int 的范围是 9223372036854775807,即19 digits long。我的最终预期答案 156C12=281014969393251275 是 18 digits long在 long long int 的范围内
    猜你喜欢
    • 2012-04-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-04
    • 2013-07-28
    • 2017-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多