寻找1-1000000之间的最大Collat​​z序列

时间:2014-01-23 18:21:45

标签: c++ collatz

我正在尝试找到1到1000000之间的最大Collatz sequence。我在下面编写了以下代码。我想这是正确的,但它非常慢。你能给我一些提示,让它更快吗?感谢。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
bool myfn(int i, int j) { return i<j; }

int collatz(int x);

int main()
{
    vector <int> myvector;
    for(int i = 1; i < 1000000; i++)
    {
        myvector.push_back(collatz(i));
    }

    cout<<*max_element(myvector.begin(),myvector.end(),myfn);


    return 0;

}

int collatz(int x)
{
    int counter = 1;


    while(1)
    {
        if(x == 1)
            break;

        if(x % 2 == 0)
        {
            x = x / 2;
            counter++;
        }
        else
        {
            x = 3 * x + 1;
            counter++;
        }
    }

    return counter;
}

2 个答案:

答案 0 :(得分:4)

实际上,我刚测试过,你的代码不只是“非常慢”,而是无限循环。不,你不仅反驳了Collat​​z猜想,但据我所知,你正遭受整数溢出。

更具体地说,在collatz(113383)期间int x变量由于溢出而变为负数:

551580299 1654740898 827370449 -1812855948 -906427974 -453213987

在此之后不久,它开始循环以下序列,因此永远不会退出循环

-37 -110 -55 -164 -82 -41 -122 -61 -182 -91 -272 -136 -68 -34 -17 -50 -25 -74 -37 ...

int x参数更改为long long后,程序很快就完成了。

当然,问题仍然是不会发生不会导致无限循环并且不被注意的溢出,因为您仍然会得到错误的答案。但是,在放了

之后
if (x < 0) {
    cout << "ERROR" << endl;
}

while(1)循环的末尾并且看不到任何输出,我认为你可以确信long long对于数字1到1000000(8字节)的Collat​​z序列足够大在我的计算机上,与int的4个字节相比,如果你有兴趣的话。)

编辑: 作为旁注:如果您只需要最大值,我认为没有任何理由保留所有结果的向量。以下代码会占用更少的内存:

int maxCollatz = 0;
for(int i = 1; i < 1000000; i++) {
    if (i % 10000 == 0)
        cout << i << endl;
    maxCollatz = max(maxCollatz, collatz(i));
}

另一个注意事项:你实际上只是从1到999999循环,所以如果100万的Collat​​z序列是最长的,你可能会错过那个......

答案 1 :(得分:2)

以下是一些提示:

将矢量初始化为您的容量。
在推动元素时,矢量可能正在扩展。最糟糕的情况是,每次push_back重新分配一次。

将矢量视为数组
将向量初始化为其容量后,可以使用运算符[]访问向量槽而不是调用push_back

优化collat​​z
这可能是你的瓶颈。尝试放入一个单独的文件,并在其上启动编译器优化。

可能有更优化的算法。