您的位置:首页 > 其它

3n+1_problem_Uva

2016-04-30 22:49 387 查看
这道题,其实说难也难,说简单也简单,关键在其测试数据。如果测试数据很苛刻,就很难了(参看博客UVa Problem 100 The 3n+1 problem (3n+1 问题))。

这里,我要写两点想法:第一,题目中说求数字i,j之间的最大循环节长度,但是样例输入却都是按min,max的顺序给出,这让我们产生了一种错觉:输入就是按较小数、较大数输入的,这也是我多次TL的原因。记住:当题目要求模棱两可的时候,一定要注意其真正的意思,不要带入自己的观念。第二,我列举了10以内数的循环节长度,发现相邻两个数中奇数较大时,奇数的循环节长度一般比偶数的大;但是如果偶数较大时,这个就不成立,因此,当一个范围的最大数是偶数的时候,要单独计算其循环节长度,剩下的就归结为前一类情况了,也就可以只计算奇数的循环节长度(这里是不严格的推广)。另外,一个范围(min到max)内的大数部分(从max/2到max部分的数)比小数部分(min到max/2)的最大循环节长度大。所以有了下面的程序:

#include<stdio.h>
int main()
{
int min,max,min_o,max_o;
int i,tmp,rst,count;
char input[100];

while(gets(input))/*处理循环输入*/
{
rst = 0;
sscanf(input,"%d %d",&min_o,&max_o);
if(max_o > min_o )
{
min = min_o;
max = max_o;
}
else
{
max = min_o;
min = max_o;
}

if(max%2 == 0)/*单独处理偶数最大上限,下面只判断奇数*/
{
count = 0;
tmp = max;
while(tmp != 1)/*处理最大数*/
{
if(tmp%2 == 0)
tmp /= 2;
else tmp = tmp*3 + 1;

count ++;
}
if(count > rst)/*记录最大数*/
rst = count;
}

tmp = max/2;/*范围的大数部分*/
if(tmp%2 == 0)
tmp ++;

if(tmp < min)/*修正范围*/
{
if(min%2 == 0)
tmp = min + 1;
else tmp = min;
}

for(i = tmp;i <= max;i += 2)/*循环这个范围内的大数那部分*/
{
tmp = i;
count = 0;
while(tmp != 1)/*处理每一个数*/
{
if(tmp%2 == 0)
tmp /= 2;
else tmp = tmp*3 + 1;

count ++;
}
if(count > rst)/*记录最大数*/
{
rst = count;
}
}
printf("%d %d %d\n",min_o,max_o,rst + 1);/*按输入的顺序输出i,j*/
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: