码迷,mamicode.com
首页 > 其他好文 > 详细

UVa 100 - The 3n + 1 problem

时间:2014-09-30 20:54:00      阅读:177      评论:0      收藏:0      [点我收藏+]

标签: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

 

 

 

 

 

UVa 100 - The 3n + 1 problem

标签:style   blog   color   io   os   ar   for   sp   div   

原文地址:http://www.cnblogs.com/8313-7386/p/4002626.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!