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