题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1032
题意:
题的大意是输入两个数(注意,这里没有说第一个数一定要小与第二个数),然后对这两个数之间的所有整数包括端点的数,进行一种规律运算,并求出运算的次数,比较所有的数规律运算次数,输出最大的.
分析:此题数据比较大1-1000000,一般的暴力循环或者递归会超时(这道题hdu的数据并不大,所以你暴力也能过)。不过这道题正解可以用记忆化+打表,直接打表要是数据比较强也会爆。观察发现,比如计算n=8,依次输出8,4,2,1,长度为4;n=16时,输出16,8,4,2,1,长度为5。额...与n=8时计算有重复了,长度可以表示为1+len(8);归纳得出:
如果n是奇数,len(n)=1+len(3*n+1);如果n是偶数,len(n)=1+len(n/2);记忆化做了。
#include <stdio.h>
#define MAX 1000000
#define ll long long
using namespace std;
int sum[1000001]={0};
int m,n;
int dfs(ll k)//注意k如果是int会溢出
{
if(k<=MAX && sum[k])//记忆化保存前1000000就行了,后面的就直接算
return sum[k];
int ans=1;
if(k%2==0)
ans+=dfs(k/2);
else
ans+=dfs(k*3+1);
if(k<=MAX)
sum[k]=ans;
return ans;
}
int main()
{
sum[1]=1;
for(int i=2;i<=1000000;i++)
sum[i]=dfs(i);
while(scanf("%d%d",&m,&n)!=EOF)
{
printf("%d %d ",m,n);
if(m>n)
{
int t=m;
m=n;
n=t;
}
int max=0;
for(int i=m;i<=n;i++)
if(max<sum[i])
max=sum[i];
printf("%d\n",max);
}
return 0;
}