这道题,其实说难也难,说简单也简单,关键在其测试数据。如果测试数据很苛刻,就很难了(参看博客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; }