题目链接:

http://acm.zzuli.edu.cn/problem.php?id=2597

题目描述
大家想必都知道角谷猜想,即任何一个自然数,如果是偶数,就除以2,如果是奇数,就乘以3再加1。最后,经过若干次迭代得到1。也就是说,不管怎样迭代,不断除以2以后,最后是1,我们称一个数字经过角谷猜想变化得到1迭代的次数称为角谷序列步长,例如数字3,它的角谷猜想变化过程为3->10->5->16->8->4->2->1,所以它的角谷序列步长为8。小D同学想知道区间[1,n]内,角谷序列步长最大的那个数字是谁?
输入
多组测试数据,以EOF结束
每组测试数据一行,每行一个正整数n(1<=n<=4000000)。
输出
对于每组测试数据输出一行,每行一个数字,表示区间[1,n]内角谷序列步长最大的那个数字,如果这样的数字有多个,输出最小的那个
样例输入 
1
2
3
样例输出 
1
2
3
这题n给的数字很大,显然需要我们打表,而且直接打表的话也很浪费时间,所以我们可以用记忆化搜索的方式,储存之前计算的值在之后计算用的时候用上以减少计算量
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<cmath>
#include<cstdio>
#include<cctype>
#include<string>
#include<vector>
#include<climits>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define max(a, b) (a > b ? a : b)
#define min(a, b) (a < b ? a : b)
#define mst(a) memset(a, 0, sizeof(a))
#define _test printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n")
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const double eps = 1e-7;
const int INF = 0x3f3f3f3f;
const ll ll_INF = 0x3f3f3f3f3f3f3f;
const int maxn = 4e6+10;
ll res[maxn] = {0,1};
//递归
ll solve(ll x) {
    ll cnt;
    if (x < maxn && res[x]) //利用中间结果减少计算量
        return res[x];
    cnt = solve(x&1 ? x*3 + 1 : x >> 1) + 1;
    return cnt;
}
//循环版
//ll solve(ll x) {
//    ll cnt = 1;
//    while(x != 1) {
//        x&1 ? x = x*3 + 1 : x >>= 1;
//        ++cnt;
//        if (x <= maxn && res[x])
//            return cnt+res[x]-1;
//    }
//    return cnt;
//}
int main(void) {
    for(int i = 2; i<maxn; ++i)
        res[i] = solve(i);
    P _max = {res[1], 1};
    res[1] = 1;
    for(int i = 2; i<maxn; ++i) { //求解1~n内步长最大的数
        if (res[i] < _max.first)
            res[i] = _max.second;
        else if (res[i] > _max.first) {
            _max.first = res[i];
            _max.second = i;
            res[i] = i;
        }
        //printf("%lld ", res[i]);
    }
    int num;
    while(~scanf("%d", &num))
        printf("%lld\n", res[num]);
    return 0;
}
12-23 10:02