首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

UVA 100 - The 3n+1 problem (3n+1 有关问题)

2013-09-28 
UVA100 - The 3n+1 problem (3n+1 问题)100 - The 3n1 problem (3n1 问题)/** 100 - The 3n1 problem (3n1

UVA 100 - The 3n+1 problem (3n+1 问题)

100 - The 3n+1 problem (3n+1 问题)


/** 100 - The 3n+1 problem (3n+1 问题)* 作者 仪冰* QQ 974817955** [问题描述]* 考虑如下的序列生成算法:从整数 n 开始,如果 n 是偶数,把它除以 2;如果 n 是奇数,* 把它乘 3 加1。用新得到的值重复上述步骤,直到 n = 1 时停止。* 例如,n = 22 时该算法生成的序列是:* 22,11,34,17,52,26,13,40,20,10,5,16,8,4,2,1* 人们猜想(没有得到证明)对于任意整数 n,该算法总能终止于 n = 1。* 这个猜想对于至少 1 000 000 内的整数都是正确的。* 对于给定的 n,该序列的元素(包括 1)个数被称为 n 的循环节长度。* 在上述例子中,22 的循环节长度为 16。* 输入两个数 i 和 j,你的任务是计算 i 到 j(包含 i 和 j)之间的整数中,* 循环节长度的最大值。* [输入]* 输入每行包含两个整数 i 和 j。所有整数大于 0,小于 1 000 000。** [输出]* 对于每对整数 i 和 j,按原来的顺序输出 i 和 j,然后输出二者之间的整数中的最大循环节长度。* 这三个整数应该用单个空格隔开,且在同一行输出。* 对于读入的每一组数据,在输出中应位于单独的一行。*[样例输入]1 10100 200201 210900 1000[样例输出]1 10 20100 200 125201 200 27900 1000 174* [解题方法]* 计算每个数的循环节长度,求给定区间的最大值。** 需要注意:* 1.中间计算过程有的数据会超出int 或 long 型范围,应该用long long型。* 2.输入的两个数,应该比较大小,判断出左区间和右区间。* 3.直接按部就班的计算会time limited(超时),这里采用填表的方法,*   把算出来的结果保存在一个全局数组中,这样以后用到的时候,直接拿来用,节省时间,避免超时。*/#include<iostream>#include<cstring>using namespace std;const int MAXN = 1000000;  //右端点最大值int MediaVariableArray[MAXN];  //保存区间中所有的循环节长度,这是对填表的应用int LoopNodeLength (long long EveryNumber);  //计算循环节长度int main(){    int firstnumber = 0;        //输入的第一个数    int secondnumber = 0;       //输入的第二个数    int nodeleft = 0;           //区间左端点    int noderight = 0;          //区间右端点    int loopnodemax = 0;        //保存最大长度的循环节    int everynodelength = 0;    //保存区间中单个数的循环节长度    memset(MediaVariableArray, 0, sizeof(MediaVariableArray)); //初始化,都置为0    while (cin >> firstnumber >> secondnumber)    {        if (firstnumber > secondnumber)  //判断左端点和右端点        {            nodeleft = secondnumber;            noderight = firstnumber;        }        else        {            nodeleft = firstnumber;            noderight = secondnumber;        }        loopnodemax = 0; //初始化最大值        for (int i=nodeleft; i<=noderight; i++)        {            everynodelength = LoopNodeLength(i);            if (everynodelength > loopnodemax) //判断是否更新最大值            {                loopnodemax = everynodelength;            }        }        cout << firstnumber << " " <<secondnumber << " ";        cout << loopnodemax << endl;    }    return 0;}int LoopNodeLength(long long EveryNumber){    if (EveryNumber == 1)    {        return 1;    }    if (EveryNumber & 1)  //按位与1 等价于 对2求模;左移 等价于 乘以2,同理右移是除以2。    {        //计算n = 3n + 1;        //左移运算符比加号优先级低,所以加括号;        //我建议不管怎样,为了代码易读都应该加上必要的括号。        EveryNumber = EveryNumber + (EveryNumber<<1) + 1;    }    else    {        EveryNumber >>= 1;  //n = n / 2    }    //如果中间计算值小于MAXN就看看我们先前求没求出它的循环节长度,    //如果求出来了,直接拿来用,节省时间。    if (EveryNumber < MAXN)    {        if (MediaVariableArray[EveryNumber] == 0)        {            MediaVariableArray[EveryNumber] = LoopNodeLength(EveryNumber);        }        return MediaVariableArray[EveryNumber] + 1;    }    return LoopNodeLength(EveryNumber) + 1;}


热点排行