zzulioj - 2597: 角谷猜想2

题目链接:

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

  这题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;
}

 

posted @ 2019-12-19 22:07  shuitiangong  阅读(300)  评论(0编辑  收藏  举报