标签:style blog color io os ar for sp div
这道题很简单,不过它的背景(克拉兹问题,或称角谷猜想)却不是那么简单。至今仍未有人给出一个可靠的证明。
分析:
只需枚举给定范围内的每一个正整数并进行模拟即可。不过这样做一定会超时,可以采取类似于记忆化的思想,将较小的数所得结果用数组保存起来,之后在计算较大的数时可以直接引用。不过,并非所有的数的结果都可以被保存起来。由实验可知,在计算过程中可能达到的数的大小远大于给定范围的上限。(见附表)所以在计算较大的数时(我取的是>=10,000,000)时需要将直接枚举与记忆化搜索相结合。我实际上试了两种方法,第一种是对>=10,000,000的数直接枚举,用时0.068s,第二种是对>=10,000,000的数进行枚举和记忆化搜索,用时0.052s,确实稍快一些。
注意事项:
1. 需要统计的数包括它本身和最后生成的1.
2. 题目中并没有限制输入的两个数i, j的相对大小,也就是说,可能出现i>j的情况,需要加以判断。
代码:
方法一:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<memory.h>
using namespace std;
typedef long long LL;
int a[10000005];
int enumerate(LL x)
{
int counts=1;
while(x!=1)
{
if(x%2==0) x/=2;
else x=x*3+1;
counts++;
}
return counts;
}
int search(LL x)
{
if(x>=10000000) return enumerate(x);
if(a[x]!=-1) return a[x];
if(x%2==0)
return a[x]=search(x/2)+1;
else
return a[x]=search(3*x+1)+1;
}
int main()
{
int m,n,i,ans;
memset(a,-1,sizeof(a));
a[1]=1;
while(cin>>m>>n)
{
cout<<m<<‘ ‘<<n;
ans=-1;
if(m>=n) swap(m,n);
for(i=m;i<=n;i++)
ans=max(ans,search(i));
cout<<‘ ‘<<ans<<endl;
}
return 0;
}
方法二:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<memory.h>
using namespace std;
typedef long long LL;
int a[10000005];
int enumerate(LL x)
{
int counts=1;
while(x>=10000000)
{
counts++;
x = x%2==0 ? x/2 : x*3+1;
}
if(a[x]!=-1) return a[x];
if(x%2==0)
return a[x]=enumerate(x/2)+counts;
else
return a[x]=enumerate(3*x+1)+counts;
}
int main()
{
int m,n,i,ans;
memset(a,-1,sizeof(a));
a[1]=1;
while(cin>>m>>n)
{
cout<<m<<‘ ‘<<n;
ans=-1;
if(m>=n) swap(m,n);
for(i=m;i<=n;i++)
ans=max(ans,enumerate(i));
cout<<‘ ‘<<ans<<endl;
}
return 0;
}
附表:
范围 | 计算过程中可能遇到的最大值 | 答案 |
[1, 10] | 52 | 20 |
[1, 100] | 9232 | 119 |
[1, 1000] | 250504 | 179 |
[1, 10000] | 27114424 | 262 |
[1, 100000] | 1570824736 | 351 |
[1, 1000000] | 56991483520 | 525 |
标签:style blog color io os ar for sp div
原文地址:http://www.cnblogs.com/8313-7386/p/4002626.html