[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里的兄弟的启发。

下面附上代码:

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/p/1987597.html