阿bang 发表于 2018-4-4 10:20:44

import time


start = time.time()
cntlist = []
for i in range(2, 1000000):
    numlist =
    num = i
    while num != 1:
      if num % 2 == 0:
            num /= 2
      else:
            num = num * 3 + 1
      numlist.append(num)
      if num in numlist:

    cntlist.append(len(numlist))
print max(cntlist)
print time.time() - start

十分初级的版本。考虑优化点有2:

1、类似素数筛选法:已经算过的数的2的n次方倍数的数,计数直接+n,结束。
2、维护一个数的序列的表,如果出现某个数在列表内,则计数直接加上列表后面的长度,结束。

阿bang 发表于 2018-4-4 12:43:27

(837799, 524)
2.58100008965

优化了一下,速度提高了不少。不过最后的字典里取结果可能慢了。还有优化的空间。代码如下:
import time


def longestCollatz(n=1000001):
    start = time.time()
    collatzdict = {}#维护一个统一的collatz的统计字典,初始为
    numlist = * (n - 1) #默认所有数都未被‘挖掉’, 从2 开始
    for i in range(2, n):
      count = 0
      num = i
      if numlist == True: #若一个数未被挖掉,计算数量
            while num != 1:
                num = num * 3 + 1 if num % 2 else num / 2
                count += 1
                if num in collatzdict: #若计算到某个步骤,产生了已经出现过的数,则直接加上该数的计数,计数结束
                  count += collatzdict
                  break
            collatzdict = count
            numlist = False
            if i < n / 2:             #以i为基数,挖掉i的2的j次方倍的所有的数
                j = 1
                while i * pow(2, j) < n:
                  if numlist == True:
                        numlist = False #挖掉第i个数2的j次方倍的数
                        collatzdict = collatzdict + j
                  j += 1
    print list(sorted(collatzdict.items(), key=lambda x:x, reverse=True))
    print time.time() - start


if __name__ == '__main__':
    longestCollatz()

阿bang 发表于 2018-4-4 12:57:11

阿bang 发表于 2018-4-4 12:43
优化了一下,速度提高了不少。不过最后的字典里取结果可能慢了。还有优化的空间。代码如下:

import time


def longestCollatz(n=1000001):
    start = time.time()
    collatzdict = {}#维护一个统一的collatz的统计字典,初始为
    numlist = * (n - 1) #默认所有数都未被‘挖掉’, 从2 开始
    maxnum = 2
    maxcnt = 2
    for i in range(2, n):
      count = 0
      num = i
      if numlist == True: #若一个数未被挖掉,计算数量
            while num != 1:
                num = num * 3 + 1 if num % 2 else num / 2
                count += 1
                if num in collatzdict: #若计算到某个步骤,产生了已经出现过的数,则直接加上该数的计数,计数结束
                  count += collatzdict
                  break
            collatzdict = count
            if count > maxcnt:
                maxcnt = count
                maxnum = i
            numlist = False
            if i < n / 2:             #以i为基数,挖掉i的2的j次方倍的所有的数
                j = 1
                while i * pow(2, j) < n:
                  if numlist == True:
                        numlist = False #挖掉第i个数2的j次方倍的数
                        collatzdict = collatzdict + j
                        if collatzdict > maxcnt:
                            maxcnt = collatzdict
                            maxnum = i * pow(2, j)
                  j += 1


    # print list(sorted(collatzdict.items(), key=lambda x:x, reverse=True))
    print maxnum, maxcnt
    print time.time() - start


if __name__ == '__main__':
    longestCollatz()

再改了一下,只需要找最大的,不需要最后排序字典的话,会快一点

837799 524
1.69199991226

najin 发表于 2018-4-7 23:01:23

The answer is 837799
Its length is 525
Time is 136 ms

jerry-R 发表于 2018-4-17 16:03:17

0.80s在此哦~~~~
#include <iostream>
using namespace std;

int main()
{
        int longest = 0;
        int terms = 0;
        int i;
        unsigned long j;

        for (i = 1; i <= 1000000; i++)
        {
                j = i;
                int this_terms = 1;

                while (j != 1)
                {
                        this_terms++;

                        if (this_terms > terms)
                        {
                                terms = this_terms;
                                longest = i;
                        }

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

        cout << longest << endl << terms << endl;
        system("pause");
        return 0;
}

zzzgod 发表于 2018-6-28 05:27:34

#include <iostream>
#include <cstring>

using namespace std;

int main()
{
        bool dest;
        long long maxtime=0,maxnum=0,time,num;
        memset(dest,0,1000001);
        dest=1;
        for(int i=1;i<=1000000;++i)
        {
                if(dest==1)
                        continue;
                num=i;
                time=1;
                while(num!=1)
                {
                        ++time;
                        if(num<=1000000)
                                dest=1;
                        if(num%2==0)
                        {
                                num/=2;
                        }
                        else
                        {
                                num=num*3+1;
                        }
                }
                if(time>maxtime)
                {
                        maxtime=time;
                        maxnum=i;
                }
        }
        cout<<"最长的序列数是:"<<maxnum<<' '<<"总共有:"<<maxtime<<"个元素";
}
不到1秒

山有扶苏啊 发表于 2018-10-22 17:11:08

def Collatz(n):
    t = 0
    while n != 1:
      if n%2 == 0:
            n = n/2
            t += 1
      else:
            n = 3*n + 1
            t += 1
    return t

result = {}
for i in range(1, 1000000):
    result = Collatz(i)

max(result, key = result.get)


837799

k往事如烟k 发表于 2019-3-24 01:31:03

count1 = 1
num1 = 1
for n in range(1, 1000001):
    count = 1
    num = n
    while 1:
      if num % 2 == 0:
            num //= 2
            count += 1
      else:
            num = num * 3 + 1
            count += 1
      if num == 1:
            break
    if count >= count1:
      count1 = count
      num1 = n
print(num1)

837799

王小召 发表于 2019-4-24 10:29:40

最大值:525
对应数值:837799
总用时:25.376614736835744

import time


def get_longer(num):
    if num <= 1000000:
      counter = 1
      while num != 1:
            if num % 2:
                num = num*3 + 1
            else:
                num = num/2
            counter += 1
      return counter
    else:
      raise ValueError

t1 = time.clock()
num_list =
print("最大值:{} \n对应数值:{} \n总用时:{}".format(max(num_list), num_list.index(max(num_list))+2, time.clock() - t1))

cwhsmile 发表于 2019-4-25 18:44:20

import time
import math
import functools

def test1():
    max_len = 0
    i = 1000001
   
    while i > 1:
      num = i
      count = 1
      while num != 1:
            if num%2 == 0:
                num = num//2
            else:
                num = 3*num + 1
            count += 1
      if max_len < count:
            max_len = count
            max_num = i
      i -= 2
    return max_len,max_num

start = time.perf_counter()

print(test1())
end = time.perf_counter()
print(end-start)

永恒的蓝色梦想 发表于 2020-4-19 13:02:33

本帖最后由 永恒的蓝色梦想 于 2021-2-18 11:51 编辑

C++ 12ms#include<iostream>

constexpr unsigned int MAX = 1000000;
unsigned short cache = { 0, 1 };



unsigned short Collatz(unsigned int num)noexcept {
    if (num < MAX) {
      if (cache) {
            return cache;
      }

      if (num & 1) {
            return cache = Collatz((num >> 1) + num + 1) + 2;
      }

      return cache = Collatz(num >> 1) + 1;
    }

    if (num & 1) {
      return Collatz((num >> 1) + num + 1) + 2;
    }

    return Collatz(num >> 1) + 1;
}



int main() {
    using namespace std;
    ios::sync_with_stdio(false);

    unsigned int num, max_num = 0;
    unsigned short len, max_len = 0;


    for (num = 1; num < MAX; num++) {
      if (!cache) {
            if (num & 1) {
                len = Collatz((num >> 1) + num + 1) + 2;
            }
            else {
                len = Collatz(num >> 1) + 1;
            }

            if (len > max_len) {
                max_len = len;
                max_num = num;
            }
      }
    }


    cout << max_num << endl;
    return 0;
}

leon0149 发表于 2020-5-10 19:01:15

525 837799
0.788s
#include <stdio.h>
#include <stdlib.h>

#define MAX 1000
#define NUM 1000000

long long odd(long long);
long long even(long long);
void init(long long *);
void Insert(long long *, long long);

void init(long long* array){
    array = 0;
}

void Insert(long long* array, long long e){
    if (array == MAX)
      exit(EXIT_FAILURE);
    array[++array] = e;
}

void execute(long long *array, long long e){
    long long temp = e;
    Insert(array, temp);
    while (temp != 1) {
      if (temp % 2 != 0) {
            temp = odd(temp);
            Insert(array, temp);
      }
      if (temp % 2 == 0) {
            temp = even(temp);
            Insert(array, temp);
      }
    }
}

long long odd(long long num){
    return 3 * num + 1;
}

long long even(long long num){
    return num / 2;
}

int main(void)
{
    int max = 0;
    int maxNum = 0;
    int temp;
    long long array = {0};
    for (int i = NUM - 1; i > 1; i-=2) {
      init(array);
      execute(array, i);
      temp = (int)array;
      if (max < temp){
            maxNum = i;
            max = temp;
      }
    }

    printf("最大链长: %d, 数字: %d\n", max, maxNum);
   
    return 0;
}

数据小随从 发表于 2020-6-27 18:07:01

本帖最后由 永恒的蓝色梦想 于 2020-6-30 18:00 编辑

#include<stdio.h>
#include<stdlib.h>


void main()
{
        int i, k;//定义一个整数变量,从1遍历到一百万
        int t;
        int n = 1;
        int max = 1;
        for (i = 2; i <= 5; i++)
        {
                t = i;
                n = 1;
                while (t != 1)
                {
                        if (t % 2 == 0)
                        {
                                t = t / 2;
                                n++;
                        }
                        else
                        {
                                t = (t * 3) + 1;
                                n++;
                        }
                        if (t == 1)
                                if (n > max)
                                {
                                        max = n;
                                        k = i;
                                }
                }
        }
        printf("%d,%d\n", max, k);



        system("pause");
}

有马_冬巳 发表于 2020-10-8 10:49:19

'''以下迭代序列定义在整数集合上:
n → n/2 (当 n 是偶数时)
n → 3n + 1 (当 n 是奇数时)
应用以上规则,并且以数字 13 开始,我们得到以下序列:
13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1
可以看出这个以 13 开始以 1 结束的序列包含 10 个项。虽然还没有被证明(Collatz 问题),但是人们认为在这个规则下,以任何数字开始都会以 1 结束。
以哪个不超过 100 万的数字开始,能给得到最长的序列?
注意: 一旦序列开始之后,也就是从第二项开始,项是可以超过 100 万的。'''

def longestsequence(num_of_sequence):
    number = 1
    longest = 1
    memory = {}
    while number <= num_of_sequence:
      #print("这是%d的序列:" %number)
      temp = 1
      lonumber = number
      while True:
            if lonumber == 1:
                #print(lonumber)
                break
            elif lonumber % 2 == 0:
                #print(lonumber)
                lonumber = int(lonumber / 2)
                temp += 1
                if memory.__contains__(lonumber):
                  temp += memory - 1
                  break
            elif lonumber % 2 == 1:
                #print(lonumber)
                lonumber = 3*lonumber + 1
                temp += 1
                if memory.__contains__(lonumber):
                  temp += memory - 1
                  break
      if temp > longest:
            longest = temp
            longestnumber = number
      memory = temp
      number += 1
      #print("--------")

    print("在不超过%d的数字中,能得到最长序列的数字是%d" %(num_of_sequence,longestnumber))
    print("该数字序列量为: %d" %longest)
    #print(memory)

start_longestsequence = time.time()
longestsequence(1000000)
time_longestsequence = time.time() - start_longestsequence
print("%f秒" %time_longestsequence)



在不超过1000000的数字中,能得到最长序列的数字是837799
该数字序列量为: 525
2.077740秒

做一个字典去存储已经计算过的序列,之后再遇到那一段同样的序列就可以直接加上已储存的值,这个方法把整个程序从33秒提升到2秒

gonorth 发表于 2020-11-5 19:57:15

def f():
    record = []
    for n in range(13,14):
      count = 1
      while1 :
            if n % 2 == 0:
                n = n // 2

                count += 1
            if n % 2 != 0 and n > 1:
                n = 3 * n + 1
                count += 1
            if n == 1:
                count
                #print (count)
                break
      record.append(count)
      count = 1
    return max(record)




print (f())

卢本伟牛逼 发表于 2021-8-13 23:46:01

#include <stdio.h>
#include <math.h>

static int flag;//计数器

int Collatz2(long long int value){//2、非递归
        int count = 0;
        while(value > 1){
                flag++;
                value = (value%2)?value * 3 + 1: value / 2;
                count += 1;
        }
        return count + 1;
}

int main(void)
{
        int i;
        int max_Collatz_num;
        int max;
        int temp;

        for(i=1;i<1000000;i++){
                temp = Collatz2(i);
                if (temp > max){
                        max = temp;
                        max_Collatz_num = i;
                }
        }

        printf("max_Collatz_num = %d, count = %d\n", max_Collatz_num, Collatz2(max_Collatz_num));
        printf("flag = %d\n", flag);

        return 0;
}
//max_Collatz_num = 837799, count = 525
//flag = 131434796

ft215378 发表于 2021-10-13 13:09:09

FlySelf 发表于 2017-2-7 11:24
执行结果:

程序执行了3.018928s。

番杰 发表于 2021-10-29 10:50:39

#include<stdio.h>

#define MAX1000000

typedef unsigned int   UINT;
int len = 0;

int Odd_or_Even(UINT);

int main(void)
{
        unsigned int Max_len = 0,Max_num = 0;
       
        for(int i = 1;i < max;i++)
        {
                len = 0;
                Odd_or_Even(i);
                if(Max_len < len )
                {
                        Max_len = len;
                        Max_num = i;
                }
        }
       
        printf("%d,%d",Max_len,Max_num);
       
        return 0;
}

int Odd_or_Even(UINT num)
{
        len ++;       
       
        if(num == 1)
                return 1;
        else
        {
                if(num % 2 ==0)
                        Odd_or_Even((num / 2));
                else
                        Odd_or_Even((num * 3 + 1));
        }
       
        return 0;
}

guosl 发表于 2022-1-2 18:57:46

本帖最后由 guosl 于 2022-1-2 19:03 编辑

/*
答案:837799
耗时:0.411748秒(单核)
      0.0373096秒(八核)
*/
#include <iostream>
#include <omp.h>
using namespace std;

const int N = 1000000;

int main(void)
{
volatile int nMaxLen = 0, nVal = 0;
#pragma omp parallel for shared(nMaxLen,nVal) schedule(dynamic,16)
for (int i = 1; i <= N; ++i)
{
    int nStep = 1;
    long long l = i;
    while (l != 1LL)
    {
      if (l % 2LL == 0)
      l = l >> 1;
      else
      l = 3LL * l + 1LL;
      ++nStep;
    }
    if (nStep > nMaxLen)
    {
#pragma omp critical
      {
      nMaxLen = nStep;
      nVal = i;
      }
    }
}
cout << nVal << endl;
return 0;
}

jerryxjr1220 发表于 2022-2-24 21:36:24

package main

import (
        "fmt"
        "time"
)

//题目14:
//
//以下迭代序列定义在整数集合上:
//
//n → n/2 (当 n 是偶数时)
//n → 3n + 1 (当 n 是奇数时)
//
//应用以上规则,并且以数字 13 开始,我们得到以下序列:
//
//13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1
//
//可以看出这个以 13 开始以 1 结束的序列包含 10 个项。虽然还没有被证明(Collatz 问题),但是人们认为在这个规则下,以任何数字开始都会以 1 结束。
//
//以哪个不超过 100 万的数字开始,能给得到最长的序列?
//
//注意: 一旦序列开始之后,也就是从第二项开始,项是可以超过 100 万的。

var n = mapint64{
        1: 1,
        2: 2,
}

func If(b bool, vt int64, vf int64) int64 {
        if b == true {
                return vt
        } else {
                return vf
        }
}

func loop(a int64) int64 {
        t := a
        var c int64 = 0
        for n == 0 {
                t = If(t%2 == 0, t/2, t*3+1)
                c++
        }
        n = n + c
        t = If(a%2 == 0, a/2, a*3+1)
        p := a
        for n == 0 {
                n = n - 1
                p = t
                t = If(a%2 == 0, a/2, a*3+1)
        }
        return n
}

func main() {
        t := time.Now()
        var i int64
        for i = 3; i < 1000000; i++ {
                _ = loop(i)
        }
        var max = mapint64{
                "key":   1,
                "value": 1,
        }
        for key, value := range n {
                if value > max["value"] {
                        max["value"] = value
                        max["key"] = key
                }
        }
        fmt.Println(max)
        tt := time.Now()
        fmt.Println("耗时:", (tt.Nanosecond()-t.Nanosecond())/1e6, "ms")
}

输出:
map
耗时: 309 ms
页: 1 [2] 3
查看完整版本: 题目14:找出以100万以下的数字开始的最长序列