3n+1数链问题

本文探讨了递归算法在解决特定数学问题时的应用,并通过动态规划的方法进行优化,以减少重复计算,提高效率。文章提供了两个不同实现方式的代码示例:一个使用递归加缓存的方法,另一个则是简单的暴力求解。

用时间换空间,然而需要的空间太大,卡在第6个样例,我觉得应该可以压缩的。

#include <stdio.h>
#include <string.h>

int const maxn = 7000000;  //不知道上限在哪里 
int g_a[maxn];
int g_i,g_j;
int g_ans=0;

int dfs(int i) {
    if (g_a[i]!=-1) return g_a[i];
    int & tmp = g_a[i];
    if(i==1) {
        tmp=1;
        return tmp;
    }
    if(i%2==0) {
        tmp = dfs(i/2)+1;
        return tmp;
    }
    if (i%2==1) {
        tmp = dfs(i*3+1)+1;
        return tmp;
    }

}



int main() {
    scanf("%d%d",&g_i,&g_j);
    memset(g_a,-1,sizeof(g_a));
    for(int i=g_i;i<=g_j;i++) {
        int k = dfs(i);
        if(k>g_ans) g_ans = k;
    }
    printf("%d\n",g_ans);
}

朴素的暴力求解:

#include<stdio.h>
int length( int n );

int main()
{
    int i, j;
    int k;
    int max = 0;

    scanf("%d %d", &i, &j );

    for ( k = i; k <= j; k++ )
    {
        if ( length(k) >= max )
        {
            max = length(k);    /* 更新最大值 */
        }
    }

    printf( "%d\n", max );

    return 0;
} 

int length( int n )
{
    int length = 1;

    while ( n != 1 )
    {
        if ( n % 2 == 1 )
        {
            n = n * 3 + 1;
        }
        else
        {
            n /= 2;
        }

        length++; 
    }

    return length;
}
### 问题分析 该问题要求计算在指定范围内所有正整按照“3n+1”规则生成的长度,并找出其中的最大长。具体规则如下:从一个正整 `n` 开始,如果 `n` 是奇,则下一项为 `3n + 1`;如果是偶,则下一项为 `n / 2`。重复此过程直到 `n` 变为 1长定义为中出现的字个(包括初始值和最终的 1)[^1]。 ### 实现思路 为了实现上述功能,可以采用循环结构对每个输入范围内的整进行处理: 1. 对于每个整 `i`,初始化计器 `count` 为 1(因为起始值本身计入长)。 2. 使用 `while` 循环模拟生成过程,直到 `n` 变为 13. 每次变换后增加计器。 4. 记录所有整中最大的长。 此外,为了提高效率,可以使用记忆化技术缓存已经计算过的值的长,避免重复计算。 ### C++ 示例代码 以下是一个基于上述逻辑的完整 C++ 程序示例: ```cpp #include <iostream> #include <fstream> #include <vector> int computeChainLength(int n, std::vector<int>& memo) { if (n == 1) return 1; if (memo[n] != 0) return memo[n]; // 如果已经计算过,直接返回结果 if (n % 2 == 0) memo[n] = 1 + computeChainLength(n / 2, memo); else memo[n] = 1 + computeChainLength(3 * n + 1, memo); return memo[n]; } int main() { int a, b; std::ifstream fin("chain.in"); fin >> a >> b; fin.close(); std::vector<int> memo(1000000, 0); // 假设最大输入不超过一百万 int max_length = 0; for (int i = a; i <= b; ++i) { int length = computeChainLength(i, memo); if (length > max_length) max_length = length; } std::ofstream fout("chain.out"); fout << max_length << std::endl; fout.close(); return 0; } ``` 该程序实现了从文件 `chain.in` 中读取输入据、计算长并输出最长长到 `chain.out` 文件的功能。通过引入记忆化组 `memo`,有效减少了重复计算,提高了执行效率[^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值