3n+1 数链问题

在计算机科学上,有很多类问题是无法解决的,我们称之为不可解决问题。然而,在很多情况下我们并不知道哪一类问题可以解决,哪一类问题不可以解决。现在我们就有一个问题,问题如下:

1、  输入一个正整数n

2、  n显示出来;

3、  如果n1则结束;

4、  如果n是奇数则n变为3×n1,否则n变为n/2

5、  转入第二步;

例如对于输入的正整数22,应该有如下数列被显示出来:

221134175226134020105168421

我们推测:对于任意一个正整数,经过以上算法最终推到1。尽管这个算法很简单,但我们仍然无法确定我们的推断是否正确。不过好在我们有计算机,我们验证了对于小于1000000的正整数都满足以上推断。

对于给定的正整数n,我们把显示出来的数定义为n的链长,例如22的链长为16

你的任务是编写一个程序,对于任意一对正整数ij,给出ij之间的最长链长,当然这个链长是由ij之间的其中一个正整数产生的。我们这里的ij之间既包括i也包括j

输入输出样例:

Simple input

Output for the input

1 10

8 8

100 200

201 210

20

4

125

89

 

解:

本题没什么特殊技巧,最简单的就是用穷举法一个个比较。

代码:

   

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

int  link3( int  data){
    
int  count = 1 ;
    
while (data != 1 ){
        
if (data % 2 == 0 )    data /= 2 ;
        
else  data = data * 3 + 1 ;
        
++ count;
    }
    
return  count;
}


void  main(){
    
int  max,i,j,t;
    
while ( 1 ){
        scanf(
" %d%d " , & i, & j);
        
if (i == 0   &&  j == 0 ) exit( 0 );
        max
= 0 ;
        
for (;i <= j;i ++ ){
            t
= link3(i);
            
if (t > max) max = t;
        }
        printf(
" %d " ,max);
    }
}

### 问题分析 该问题要求计算在指定范围内所有正整数按照“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]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值