题目链接:
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)。
每组测试数据一行,每行一个正整数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; }