现在的位置: 首页 > 综合 > 正文

[数论][题目]3n+1数链问题

2017年11月12日 ⁄ 综合 ⁄ 共 2073字 ⁄ 字号 评论关闭

题目描述:

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

(1)       输入一个正整数n;

(2)       n显示出来;

(3)       如果n=1则结束;

(4)       如果n是奇数则n变为3n+1,否则n变为n/2

(5)       转入第(2)步。

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

22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1

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

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

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

输入格式:

两个正整数i, j 从文本文件LINK.DAT输入,文件只有一行,即为正整数ijij之间以一个空格隔开。0<ij<10000;

输出格式:

要求将你的程序的运行结果写入文本文件LINK.OUT中,文件只能有一行,即为ij之间的最长链长。

输入输出样例:

输入样例:

1 10

 

输出样例:

20

 

题解:

       题目开始的都是些废话~~当然ACM的题目里有很多这种啰嗦的东西,不过看起来倒是觉得挺让人心暖和的,不像国内的题目都是直接往主题裸奔。

       接着给出了一个很简单的递推公式,让你将一个输入的正整数n进行反复的变换:当是偶数时 n=n/2 奇数时n=3n+1。虽然没有说这个是得到证明的结果,但是从后面的输入格式的限制条件(0<ij<10000)来看,显然我们可以认为,这种变换最终会让n成为1,而这也是递推结束的标志。

然后,我们还知道这种变换所产生的数的个数被称为3n+1链的长度。而最终所要求的输出是在给出的ij之间所有正整数的3n+1链长之中最长的一个。例如对样例来说:

       正整数                         1     2     3     4     5     6     7     8     9     10

       对应的3n+1链长         1     2     8     3     6     9     17    4     20    7

       最长的链长应该为n=9时的链长:20

分析:

       这其实是很简单的一题,如果需求仅仅是解决规模010000的数,那么我们只需要像用傻瓜照相机一样跟着说明做就好了。

       首先,我们必须根据3n+1链的说明根据一个数模拟实现整个链,然后统计其链长。

       之后,我们可以根据这个实现,计算从ij所有整数的链长,并保留其中最大的那个即可。

 

参考代码:

#include <iostream>

#include <fstream>

 

using namespace std;

 

// n3n+1链长函数

int LnkLength( int n)

{

     int Length = 1;

     while (n!=1)

     {

         if ( n&1 == 1 )         // 奇偶性判断

              n = 3*n + 1;

         else

              n=n>>1;             // 移位操作一般比除法操作快(不考虑编译器优化)

 

         ++Length;

     }

 

     return Length;

}

 

int main()

{

     ifstream infile("LINK.DAT", ios::in );

     ofstream outfile("LINK.OUT", ios::out );

 

     int max=0;

     int i,j,Length;

 

     infile>>i>>j;

     for ( int idx=i; idx<=j; ++idx)

     {

         Length = LnkLength(idx);

 

         max = Length>max? Length:max;

     }

 

     outfile<<max;

 

     return 0;

}

 

测试输入1             测试输入2                     测试输入3

8 8                               100 200                                201 210

测试输出1             测试输出2                     测试输出3

4                                  125                                       89

抱歉!评论已关闭.