【问题标题】:Segmentation fault for big input (recursive function)大输入的分段错误(递归函数)
【发布时间】:2021-05-23 21:43:29
【问题描述】:

`#include 使用命名空间标准; #define ll long long

    ll solve(ll a, ll b, ll i){
        //base case
        if (a == 0) return i;
        if (b > a) return i+1;

        //recursive case
        if (b == 1) {
            return solve(a,b+1,i+1);
        }
        ll n = solve(a, b+1, i+1);
        ll m = solve(a/b, b, i+1);
        return min(n,m);
    }

int main(){
int t;  
cin >> t;
while(t--){
ll a, b;
cin >> a >> b;
cout << solve(a, b, 0)<< endl;

} }`

基本上问题来自 codeforces (1485A)。问题是,当我给一些大的输入,比如 50000000 a 和 5 给 b 时,这给了我分段错误错误,而代码对于较小的输入工作正常。请帮我解决。

【问题讨论】:

  • 此代码没有任何 cmets。您是否希望我们通过分析来弄清楚它在做什么?

标签: recursion segmentation-fault


【解决方案1】:

使用递归是一个糟糕的选择。而且你需要进行所有明显的算法优化。

关键的见解是,对于在增加b 之前分裂的任何路径,都有一条在增加 b 之前不分裂的相同或更好的路径。如果您要使用这些步骤来增加数字,那么当您可以除以较大的数字时,为什么还要除以较小的数字?

有了这种洞察力,并消除了递归,这个问题很容易解决:

#include <iostream>

unsigned long long divisions(unsigned long long a, unsigned long long b)
{
    // figure out how many divide operations we need
    int ops = 0;
    while (a > 0)
    {
        a/=b;
        ops++;
    }
    return ops;
}

unsigned long long ops(unsigned long long a, unsigned long long b)
{
    // figure out how many divides we need with the smallest possible b
    unsigned long long min_ops = (b == 1) ? (1 + divisions(a, b+1)) : divisions(a, b);

    // try every sensible larger b to see if it takes fewer operations
    for (unsigned long long num_inc = 1; num_inc <= min_ops; ++num_inc)
    {
        unsigned long long ops = num_inc + divisions (a, b + num_inc);
        if (ops < min_ops)
            min_ops = ops;
    }
    return min_ops;
}

int main(void)
{
    int t;
    std::cin >> t;
    while (t--)
    {
       unsigned long long a, b;
       std::cin >> a >> b;
       std::cout << ops(a, b) << std::endl;
    }
}

同样,教训是您必须在开始编码之前进行算法优化。再多的出色编码也无法使糟糕的算法运行良好。

顺便说一句,the problem page 上有一个 巨大 提示。问题标签中的某些内容泄露了关键优化。

【讨论】:

    猜你喜欢
    • 2014-11-05
    • 1970-01-01
    • 2013-03-05
    • 2014-04-27
    • 2019-11-16
    • 2021-06-18
    • 2017-12-25
    相关资源
    最近更新 更多