引用请注明出处:http://blog.csdn.net/int64ago/article/details/7413434
本题注意两个方面:
1、虽然题目给的范围是1~1000000,其实计算的过程中的中间值有的是很大的,所以要用unsigned long long
2、不重复计算,我同时用了两种方案,一种是计算的过程中判断是否遇到已经计算过的,另一种是计算的过程中把“有意义”的中间值存了起来,然后得到结果的时候顺便回溯处理了,事实证明两种一起用效率还不错,44ms过了
#include <stdio.h>
#include <stdlib.h>
#define MAX_NUM 1000000
int cyc_num[MAX_NUM + 1]={0};
int back_cyc_num[MAX_NUM+1];
int back_len;
/* 处理连带计算出来的cyc_num[] */
void pro_back(int ret_num)
{
int i;
for(i = 0; i != back_len; ++i){
cyc_num[back_cyc_num[i]] = ret_num + back_len - i;
}
}
/*
* 计算cyc_num[num]的值
* 如果计算过程中遇到已经计算过得cyc_num[]
* 则不重复计算
*/
int do_creat_cyc(unsigned long long num)
{
int cnt = 1;
back_len = 0;
while(num != 1){
if(num % 2 == 0){
num /= 2;
} else{
num = num * 3 + 1;
}
if(num <= MAX_NUM && cyc_num[num]){
pro_back(cyc_num[num]);
return cnt + cyc_num[num];
}
back_cyc_num[back_len++] = num > MAX_NUM ? 0:num;
++cnt;
}
return cnt;
}
/*
* 计算1~1000000之间所有的cyc_num[]值
* 如果已经计算过则跳过
*/
void creat_cyc(void)
{
int i;
for(i = 1; i <= MAX_NUM; ++i){
if(cyc_num[i]){
continue;
} else{
cyc_num[i] = do_creat_cyc(i);
}
}
}
void let_small_big(int *const x, int *const y)
{
int tmp = *x;
*x = *y;
*y = tmp;
}
int get_max(int beg, int end)
{
int mmax = 0;
int i;
if(beg > end){
let_small_big(&beg, &end);
}
for(i = beg; i <= end; ++i){
if(mmax < cyc_num[i]){
mmax = cyc_num[i];
}
}
return mmax;
}
int main(int argc, char *argv[])
{
int beg, end;
creat_cyc();
while(scanf("%d%d", &beg, &end) != EOF){
printf("%d %d %d\n", beg, end, get_max(beg, end));
}
return 0;
}