冰雹数
题目描述
任意给定一个正整数N,如果是偶数,执行: N / 2;如果是奇数,执行: N * 3 + 1
生成的新的数字再执行同样的动作,循环往复。
通过观察发现,这个数字会一会儿上升到很高,一会儿又降落下来。
就这样起起落落的,但最终必会落到“1”
这有点像小冰雹粒子在冰雹云中翻滚增长的样子。
比如N=9:9,28,14,7,22,11,34,17,52,26,13,40,20,10,5,16,8,4,2,1
可以看到,N=9的时候,这个“小冰雹”最高冲到了52这个高度。
输入
输入存在多组测试数据,对于每组测试数据输入一行包含一个正整数N(N<1000000)
输出
对于每组测试数据,输出一行包含一个正整数表示答案
样例输入 Copy
10
100
样例输出 Copy
52
9232
思路
这题题目感觉讲得不清楚,实际上要输出的是从给定数1~N中,冰雹数所能达到的最大值。
解法一 循环暴力
#include <iostream>
using namespace std;
int main(){
int N;
long long max;
long long x;
while(scanf("%d",&N)!=EOF){
max=0;
for(int i=2;i<=N;i++){
x=i;
while(x>1){
if(x%2==0){
x=x/2;
}
else{
x=x*3+1;
}
//cout<<x<<endl;
if(x>max) max=x;
}
}
cout<<max<<endl;
}
return 0;
}
这个在OJ上过了。注意要用long long,max用int过不了。
解法二 动态规划
#include <iostream>
using namespace std;
int a[1000001];
int P(int i){
int x=i;
int max=0;
while(x!=1){
if(a[x]!=0){
if(max>a[x]) return max;
else{
return a[x];
}
}
if(x%2==0){
x=x/2;
}
else{
x=x*3+1;
}
//cout<<x<<endl;
if(x>max) max=x;
}
return max;
}
int main(){
a[0]=0;
a[1]=1;
int N;
for(int i=1;i<1000000;i++)
a[i]=0;
for(int i=2;i<100000;i++){
if(a[i-1]>P(i)) a[i]=a[i-1];
else a[i]=P(i);
}
while(scanf("%d",&N)!=EOF){
cout<<a[N]<<endl;
}
return 0;
}
依旧是严重超时,1000以内的数可以跑出来,10000以后的就不行了
方法三: 递归计算
#include<stdio.h>
using namespace std;
int max=0;
int a[1000001];
int R(int n)
{
if(n==1)
{
return 0;
}
else if(n%2==0)
{
n=n/2;
if(n>max)
{
max=n;
}
R(n);
}
else if(n%2==1)
{
n=(n*3+1);
if(n>max)
{
max=n;
}
R(n);
}
return 0;
}
int main()
{
int N;
while(scanf("%d",&N)!=EOF){
max=0;
for(int i=2;i<=N;i++){
R(i);
a[i]=max;
}
printf("%d\n",max);
}
return 0;
}
这个比之前两种都快很多,可以计算出1000000,但是会超时。在OJ上提交为N。