#include<iostream>
using namespace std;
int main(){
int n,cnt;
cin>>n;
for(cnt=0;n!=1;cnt++){
if(n%2)n=3*n+1;
else n=n/2;
}
cout<<cnt+1;//"cycle length"
}
题意:对n做上面代码的循环,直到n变成1,这个过程中n变成了多少个数,比如:n=22时循环中n的值依次为22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1,共有16个数,所以”cycle length”=16,其实就是循环次数+1啦。
现在给了一个区间[ i , j ],区间内每一个数都有一个”cycle length”,求最大”cycle length”是多少。
思路:如果对每个区间的每个数都硬生生的去求”cycle length”的话肯定会超时,应该用一个数组保存计算过的值,一是避免重复计算,二是在计算时当n变成了已经保存过的值,就可以直接拿来使用,不必再计算一遍
AC代码:
#include<iostream>
#include<cstdio>
using namespace std;
#define N 1000000
int a[N]={0};//记录n的"cycle length"
int i,j;
int work(){//边计算边打表
int max=0;
for(int x=i;x<=j;x++){
if(a[x]==0){//如果没有被计算过才进来计算
int n=x;
for(int cnt=0;;cnt++){
if(n<N&&a[n]){a[x]=a[n]+cnt;break;}//计算过程中如果发现n被计算过,加起来就跳出
if(n%2)n=3*n+1;
else n=n/2;
}
}
if(a[x]>max)max=a[x];//记录[i,j]内最大值
}
return max;
}
int main(){
a[1]=1;//需要一个初始值
while(scanf("%d%d",&i,&j)!=EOF){
printf("%d %d ",i,j);
if(i>j)swap(i,j);//题目没说i,j大小关系
printf("%d\n",work());
}
}