110101 The 3n+1 problem


#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <iostream>
#include <vector>

using namespace std;

typedef unsigned int UINT;
typedef unsigned short RESULT_t;
#define LIMIT 1000001

RESULT_t infos[LIMIT];

void GetBoundaries(vector<UINT>& bounds1, vector<UINT>& bounds2)
{
    UINT tmp1, tmp2;
    while(cin >> tmp1 >> tmp2)
    {
        bounds1.push_back(tmp1);
        bounds2.push_back(tmp2);
    }
}

RESULT_t GetLen(UINT value)
{
    if (value == 1)
        return 1;

    if ((value < LIMIT) && infos[value])
        return infos[value];

    RESULT_t len;
    if ((value % 2) == 1)
        len = GetLen(value * 3 + 1) + 1;
    else
        len = GetLen(value / 2) + 1;

    if (value < LIMIT)
        infos[value] = len;

    return len;
}

#define Power2(x, n) ((x) << (n))

void GetPartialMaxLenAndCleanForOdds(
    UINT lower, UINT upper, UINT currentNumber, 
    RESULT_t currentLen, RESULT_t delta, RESULT_t& maxLen)
{
    if ((currentNumber > upper) || (infos[currentNumber]))
        return;

    UINT j = (currentNumber << 1);
    if ((j > upper) || (infos[j]))
        return;

    infos[currentNumber] = currentLen;
    UINT middle = Power2(currentNumber, delta);
    UINT midUpper = (upper > middle) ? middle : upper;

    for(j = (currentNumber << 1); j <= midUpper; j <<= 1)
    {
        ++currentLen;
        infos[j] = currentLen;
    }

    if (middle < upper)
    {
        for(j = (middle << 1); j <= upper; j <<= 1)
        {
            ++currentLen;
            infos[j] = currentLen;
            ++maxLen;
        }
    }
}

void GetPartialMaxLenAndClean(
    UINT lower, UINT upper, 
    UINT currentNumber, RESULT_t& maxLen)
{
    RESULT_t currentLen = GetLen(currentNumber);
    RESULT_t tmpMaxLen = currentLen;
    UINT i;

    for(i = (currentNumber<<1); i <= upper; i <<= 1)
    {
        ++tmpMaxLen;
        infos[i] = tmpMaxLen;
    }

    if (tmpMaxLen > maxLen)
        maxLen = tmpMaxLen;

    if ((currentNumber % 2) == 1)
    {
        GetPartialMaxLenAndCleanForOdds(lower, upper, 3*currentNumber + 1, currentLen - 1, maxLen - currentLen + 1, maxLen);
    }
    else
    {
        i = currentNumber >> 1;
        if ((i % 2) == 1)
            GetPartialMaxLenAndCleanForOdds(lower, upper, 3*i + 1, currentLen - 2, maxLen - currentLen + 2, maxLen);
    }
}

RESULT_t SmartGetMaxLen(UINT lower, UINT upper)
{
    RESULT_t maxLen = 1;

    for(UINT i = lower; i <= upper; ++i)
    {
        if (infos[i])
        {
            if (infos[i] > maxLen)
                maxLen = infos[i];
            continue;
        }

        RESULT_t tmpMaxLen = 1;
        GetPartialMaxLenAndClean(lower, upper, i, tmpMaxLen);
        if (tmpMaxLen > maxLen)
            maxLen = tmpMaxLen;
    }

    return maxLen;
}

void OutputResult(UINT lower, UINT upper, RESULT_t maxLen)
{
    cout << lower << " " << upper << " " << maxLen << endl;
}

void DoJob(UINT bound1, UINT bound2)
{
    UINT lower = (bound1 > bound2) ? bound2 : bound1;
    UINT upper = bound1 + bound2 - lower;
    RESULT_t maxLen = SmartGetMaxLen(lower, upper);
    OutputResult(bound1, bound2, maxLen);
}

int main(int argc, char* argv[])
{
    infos[1] = 1;

    vector<UINT> bounds1, bounds2;
    GetBoundaries(bounds1, bounds2);

    for(UINT i = 0; i < bounds1.size(); ++i)
    {
        DoJob(bounds1[i], bounds2[i]);
    }

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值