[Problem 14]欧拉

几点:

1. 在问题规模大的时候,一定要检查选择的数据类型是否够用,会不会overflow。这里的case就是一个很好的例子。我的算法几分钟就写好了,也蛮正确的,除了对于start num i及chain中的number n的数据类型选择了int,这就导致在n被3n+1反复搞大后,超出了int的范围,变成了负数,也就进入了导致算不出结果来的死循环里(因为永远也算不到1了)。所以,切记:问题规模大的时候,一定仔细考虑清楚数据类型的选择。

2. unsigned int的数据参与大规模运算要比long long快3倍以上。这里指的是仅仅替换i和n的数据类型。

3. 在看到更多规律的基础上,我加了个map来试图减少一些运算,结果:在题目要求的1million的问题规模下,配合unsigned int的正确类型,算不出;在调整到1000以验证算法正确性的实验中,还是发现:使用map后,由于要多做很多排序和查找的工作,虽然节省了一些直接的chain中number的计算,但最终时间统计显示还是比不用map要慢。所以,在你确定要使用map时,务必考虑清楚你增加的运算和减少的运算之间的关系,不见得能改善多少算法性能,而且还容易产生副作用。算法时间复杂度的本质在于:其需要执行的基本运算的次数的多少。

4. oh,my!我终于意识到:位操作要比乘除运算高效的多!在算法中,用n&1替换n%2来判断奇数偶数,时间花费从3秒多减少到了1秒左右!这个例子,我印象很深刻,非常有意义的实验。感谢problem 14 answer thread里的兄弟的启发。

下面附上代码:

ExpandedBlockStart.gif View Code
#include  < iostream >
#include 
< map >
#include 
< ctime >
using   namespace  std;

int  _tmain( int  argc, _TCHAR *  argv[])
{
    clock_t startT 
=  clock();
    
int  maxNum  =   10 //  initialized with starting number 13's chain length.
    unsigned  int  theStartNum  =   13 ;    
    unsigned 
int  n   =   0 //  Be exact to choose its data type.
     for (unsigned  int  i  =   14 ; i  <   1000000 ; i ++ )
    {
        n 
=  i;
        
int  tempNum  =   0 ;
        
while ( true //  to calculate tempNum.
        {            
            
//  if(n%2)  //  odd. Using this, whole algorithm cost >3s.
             if (n & 1 //  using this, cost 1s or so.
            {
                n 
=   3 * +   1  ;
            }
            
else   //  even.                
            {
                
if (n  ==   16 //  minor optimization.
                {
                    tempNum 
+=   4 ;
                    
break ;
                }
                
else
                    n 
/=   2 ;
            }

            tempNum
++ ;
            
if (n  ==   1 )
                
break ;            
        }

        
if (maxNum  <  tempNum)
        {
            maxNum 
=  tempNum;
            theStartNum 
=  i;
        }
    }

    clock_t endT 
=  clock();
    
double  spentT  =  difftime(endT, startT);
    cout 
<<   " theNum is:  "   <<  theStartNum  <<  endl;
    cout 
<<   " theChain:  "   <<  maxNum  <<  endl;
    cout 
<<   " spentT: "   <<  spentT  <<  endl;

    
return   0 ;
}

 

 

转载于:https://www.cnblogs.com/taoxu0903/archive/2011/03/18/1987597.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值