鱼C论坛

 找回密码
 立即注册
查看: 5726|回复: 41

题目14:找出以100万以下的数字开始的最长序列

[复制链接]
发表于 2015-4-21 16:24:26 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
Longest Collatz sequence

The following iterative sequence is defined for the set of positive integers:

n → n/2 (n is even)
n → 3n + 1 (n is odd)

Using the rule above and starting with 13, we generate the following sequence:

13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1

It can be seen that this sequence (starting at 13 and finishing at 1) contains 10 terms. Although it has not been proved yet (Collatz Problem), it is thought that all starting numbers finish at 1.

Which starting number, under one million, produces the longest chain?

NOTE: Once the chain starts the terms are allowed to go above one million.

题目:

以下迭代序列定义在整数集合上:

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 万的。

评分

参与人数 1荣誉 +1 收起 理由
cwhsmile + 1 链长525, 数字837799用时18s

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-9-1 22:29:42 | 显示全部楼层
本帖最后由 翅膀团 于 2015-11-16 14:14 编辑
  1. #include <stdio.h>

  2. int main(void)
  3. {
  4.     int a,n,i,num,l=0;
  5.     for(n=1;n<=1000000;n++)
  6.     {
  7.         i = 1;
  8.         a = n;
  9.         while(a != 1)
  10.         {
  11.             if(a % 2)
  12.             {
  13.                 a = 3 * a + 1;
  14.                 i++;
  15.             }
  16.             else
  17.             {
  18.                 a = a / 2;
  19.                 i++;
  20.             }
  21.         }
  22.     if(i > l)
  23.     {
  24.         num = n;
  25.         l = i;
  26.     }
  27.     }
  28.     printf("不超过 100 万的数字为%d",num);
  29. }
复制代码


如果有错误希望指出
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-6-13 18:40:57 | 显示全部楼层
  1. def g(n):
  2.     if n%2==0:
  3.         return n/2
  4.     else:
  5.         return 3*n+1
  6. timesmax=0
  7. nmax=0
  8. for i in range(1,1000001):
  9.     times=1
  10.     n=i
  11.     while n!=1:
  12.         times+=1
  13.         n=g(n)
  14.    
  15.     if times>timesmax:
  16.         nmax=i
  17.         timesmax=times
  18. print(nmax,timesmax)
复制代码


837799 525
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-8-2 22:15:26 | 显示全部楼层
  1. n = 0
  2. a = 1
  3. for i in range(1,1000001):
  4.     m = 0
  5.     j = i
  6.     while j!=1:
  7.         if j % 2 == 0:
  8.             j //= 2
  9.             m += 1
  10.         else:
  11.             j = 3 * j + 1
  12.             m += 1
  13.     if m > a :
  14.         n = i
  15.         a = m
  16. print(n,a)
复制代码

答案:837799 525
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-8-24 21:16:14 | 显示全部楼层
  1. temp=1;list1 = []
  2. def Collatz():
  3.       global temp,list1
  4.       while True:
  5.             collatz = []
  6.             temp += 1
  7.             x = temp
  8.             collatz.append(temp)
  9.             if temp > 1000000:
  10.                   break
  11.             while x != 1:
  12.                   if x > 1:
  13.                         if x % 2:
  14.                               x = x * 3 + 1
  15.                               collatz.append(x)
  16.                         if not x % 2:
  17.                               x = x // 2
  18.                               collatz.append(x)
  19.                   
  20.                   if x == 1:
  21.                         list1.append(len(collatz))
  22.       return list1
  23.             
  24.                         


  25. if __name__ == '__main__':
  26.       collatz = Collatz()
  27.       collatz.sort()
  28.       print(collatz[-1])
复制代码

先得到最长的有多少位
然后根据得到的数在collatz中用index
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-8-28 10:11:28 | 显示全部楼层
  1. inline int how(unsigned int g)
  2. {
  3.         int k = 1;
  4.         unsigned int n = g;
  5.         while ( n && n!=1)
  6.         {
  7.                 if ( 0==n%2 )
  8.                 {
  9.                         n=n/2;
  10.                 }else
  11.                 {
  12.                         n=3*n+1;
  13.                 }
  14.                 k++;
  15.         }
  16.         return k;
  17. }
  18. int main()
  19. {
  20.         int maxValue = 0,n;
  21.         int max;
  22.         for ( n = 0;n<=1000000;n++)
  23.         {
  24.                 int k =  how (n);
  25.         //        std::cout<<n<<"="<<k<<std::endl;
  26.                 if( maxValue < k )
  27.                 {
  28.                         maxValue = k;
  29.                         max = n;
  30.                 }
  31.         }
  32.         std::cout<<maxValue<<" "<<max;
  33. }

复制代码


和上面的一样
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-9-18 14:18:51 | 显示全部楼层
  1. 837799 525
  2. [Finished in 64.2s]
复制代码
  1. def rule(num):
  2.         if num == 1:
  3.                 output = 0
  4.         elif num % 2:
  5.                 output = num * 3 + 1
  6.         else:
  7.                 output = num /2
  8.         return output

  9. def calc(num):
  10.         op = num
  11.         cal = 0
  12.         while op > 0:
  13.                 op = rule(op)
  14.                 cal += 1
  15.         return cal

  16. maxi = 0
  17. maxn = 0
  18. for i in range(1,1000000):
  19.         if maxi < calc(i):
  20.                 maxi = calc(i)
  21.                 maxn = i
  22. print (maxn, maxi)
复制代码

时间有点长,感觉算法应该能再优化一下。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2016-10-11 13:02:51 | 显示全部楼层
换了一种标记法,时间缩短很多
837799
[Finished in 15.6s]

  1. def rule(num):
  2.         if num == 1:
  3.                 output = 0
  4.         elif num % 2:
  5.                 output = num * 3 + 1
  6.         else:
  7.                 output = num /2
  8.         return output

  9. calc = [None]*3000001
  10. def calf(num):
  11.         for c in range(1,num+1):
  12.                 if c>1 and calc[rule(c)] != None:
  13.                         calc[c] = calc[rule(c)] + 1
  14.                 else:
  15.                         op,cal = c,0
  16.                         while op > 1:
  17.                                 op = rule(op)
  18.                                 cal += 1
  19.                         calc[c] = cal
  20.                 if c == 1: calc[c] = 0
  21.         return calc[num]

  22. calf(1000000)
  23. print calc.index(max(calc[:1000000]))
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-10-14 11:13:23 | 显示全部楼层
  1. def euler(x):
  2.     lenght = 0
  3.     result = 0
  4.     for i in range(1,x+1):
  5.         list_j = []
  6.         j = i
  7.         while j != 1:
  8.             if j%2:
  9.                 j = j*3+1
  10.             else:
  11.                 j /= 2
  12.             list_j.append(j)
  13.         if len(list_j) > lenght:
  14.             lenght = len(list_j)
  15.             result = i
  16.     return result

  17. if __name__ == '__main__':
  18.     print(euler(1000000))
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-11-16 11:33:34 | 显示全部楼层
  1. temp = 1;
  2. list1 = []
  3. while True:
  4.     collatz=[]
  5.     temp += 1
  6.     x= temp
  7.     collatz.append(temp)
  8.     if temp >= 1000000:
  9.         break
  10.     while x != 1:
  11.         if x > 1:
  12.             if x %2:
  13.                 x = x * 3 + 1
  14.                 collatz.append(x)
  15.             if not x % 2:
  16.                 x = x//2
  17.                 collatz.append(x)
  18.     list1.append(len(collatz))
  19.    
  20. list2 = list1[:]
  21. list1.sort()
  22. print(list2.index(list1[-1])+2)
复制代码

答案:837799
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-11-24 15:40:00 | 显示全部楼层
  1. endnum = 1000000
  2. def goto1(now = 13): #规则序列生成器
  3.     if now>=1:
  4.         yield now
  5.     elif now<1:
  6.         raise StopIteration('Wrong Number')
  7.     while now!=1:
  8.         if now%2==0:
  9.             now = int(now/2)
  10.         else:
  11.             now = 3*now+1
  12.         yield now

  13. # {0 : None} 结果字典{ 开始数:结果生成器 } :
  14. resdic = {snum : goto1(snum) for snum in range(1,endnum+1)}

  15. temp = [0,[]]
  16. for key in resdic:
  17.         lis = list(resdic[key])
  18.         if temp[0]<len(lis):
  19.                 temp = [len(lis),lis]

  20. print( 'startnumber:{}   length:{}   time:{}'.format(temp[1][0],temp[0],time.clock()-t) )
复制代码


startnumber:837799   length:525   time:37.26619450396688
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-1-10 13:16:28 | 显示全部楼层
本帖最后由 芒果加黄桃 于 2017-1-10 13:18 编辑
  1. # encoding:utf-8
  2. # Collatz问题
  3. from time import time

  4. def euler014(N):
  5.     tmp = N
  6.     count = 1
  7.     while tmp > 1:
  8.         count += 1
  9.         if tmp % 2 == 0:
  10.             tmp = int(tmp / 2)
  11.         else:
  12.             tmp = tmp * 3 + 1
  13.     return count

  14. def euler014_next(num, l_result):
  15.     N = len(l_result)
  16.     t = num * 2
  17.     while t < N and l_result[t] == None:
  18.         l_result[t] = int(l_result[int(t / 2)]) + 1
  19.         t *= 2
  20.     t = num
  21.     if t % 2 != 0 and t * 3 + 1 < N and l_result[t * 3 + 1] == None:
  22.         t = t * 3 + 1
  23.         l_result[t] = l_result[num] - 1
  24.         t *=2
  25.         while t < N and l_result[t] == None:
  26.             l_result[t] = int(l_result[int(t / 2)]) + 1
  27.             t *= 2
  28.             
  29. if __name__ == '__main__':
  30.     start = time()
  31.     N = 1000000
  32.     l_result = [None] * (N + 1)
  33.     l_result[0],l_result[1] = 0,1
  34.     for i in range(2, N + 1):
  35.         if l_result[i] == None:
  36.             l_result[i] = euler014(i)
  37.             euler014_next(i, l_result)
  38.     print(max(l_result),'--',l_result.index(max(l_result)))
  39.     print('cost %.3f sec' % (time() - start))
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-1-14 21:33:40 | 显示全部楼层
本帖最后由 渡风 于 2017-1-14 21:35 编辑

此代码使用MATLAB编程
Problem14所用时间7.4436秒
Problem14的答案为837799
  1. %问题14::找出以100万以下的数字开始的最长序列
  2. %细节标记法
  3. function Output=Problem14(Input)
  4. if nargin==0
  5. Input=1000000;
  6. end
  7. Rank=Input:-1:2;
  8. Nmax=0;%储存最大是数
  9. Lmax=0;%储存最大长度
  10. N=0;%临时数
  11. L=0;%临时长度
  12. Flag=zeros(1,Input-1);
  13. for ii=1:Input-1
  14.     if Flag(ii)==0%假设没有被标记,则选择
  15.         Temp=Rank(ii);
  16.         N=Rank(ii);
  17.         Flag(ii)=1;%选择之后标记
  18.     else
  19.         continue
  20.     end
  21.     while (Temp>1)
  22.         if mod(Temp,2)==0
  23.             Temp=Temp/2;
  24.         else
  25.             Temp=Temp*3+1;
  26.         end
  27.         if Temp<Input
  28.         Flag(Input-Temp)=1;%迭代的路上标记
  29.         end
  30.         L=L+1;
  31.     end
  32.      if L>Lmax;
  33.          Lmax=L;
  34.          Nmax=N;
  35.      end
  36.      L=0;
  37. end
  38. Output=Nmax;
  39. toc  
  40. disp('此代码使用MATLAB编程')
  41. disp(['Problem14所用时间',num2str(toc),'秒'])
  42. disp(['Problem14的答案为',num2str(Output)])
  43. end
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-2-7 11:24:26 | 显示全部楼层
  1. import time

  2. def collatz_sequence(number):
  3.     '求number以下的,能得到最长的序列的数字'
  4.     list_sequence = [0, 1, 2]#存储以列表下标开始的序列长度,list_sequence[0]用于存储最长序列的下标
  5.     for i in range(3, number):
  6.         count = 0
  7.         n = i
  8.         while n != 1:
  9.             if n < len(list_sequence):
  10.                 count += list_sequence[n]
  11.                 break
  12.             if n % 2 == 0:
  13.                 n = int(n / 2)
  14.             else:
  15.                 n = 3 * n + 1
  16.             count += 1
  17.         list_sequence.append(count)
  18.         if list_sequence[list_sequence[0]] < count:
  19.             list_sequence[0] = i
  20.     return [list_sequence[0], list_sequence[list_sequence[0]]]

  21. start = time.clock()
  22. print(collatz_sequence(1000000))
  23. end = time.clock()
  24. print('程序执行了%fs。' %(end - start))
复制代码

执行结果:
[837799, 525]
程序执行了3.018928s。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 3 反对 0

使用道具 举报

发表于 2017-3-14 21:49:19 | 显示全部楼层
本帖最后由 99592938 于 2017-3-14 21:52 编辑
  1. def chain(x):
  2.     if x%2:x=3*x+1
  3.     else:x=x/2
  4.     return x
  5. import time
  6. stime = time.clock()
  7. max1=0
  8. dict1={}
  9. for i in range(2,1000000):
  10.     temp=i
  11.     count=0
  12.     while i!=1:
  13.         if i in dict1:
  14.             dict1[temp]=dict1[i]+count
  15.             break
  16.         else:
  17.             i=chain(i)
  18.             count+=1
  19.     if not(temp in dict1):dict1[temp]=count
  20.     if max1<dict1[temp]+1:
  21.         max1=dict1[temp]+1
  22.         num=temp
  23. print('The start number is %d,the longest chain is %d' %(num,max1))
  24. etime= time.clock()
  25. print('read:%.3f s' %(etime-stime))
复制代码

>>>
The start number is 837799,the longest chain is 525
read:9.211 s
加了字典优化后,效率提升很高。
优化前要跑130多秒。
然而感觉还能优化,但我已力不从心。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-4-2 18:52:15 | 显示全部楼层
本帖最后由 JonTargaryen 于 2017-4-2 19:05 编辑
FlySelf 发表于 2017-2-7 11:24
执行结果:
[837799, 525]
程序执行了3.018928s。


你这个好棒!手动点赞!C语言秒出结果。

  1. #include <stdio.h>

  2. #define MAX 1000000

  3. int main()
  4. {
  5.     int num;
  6.     long a;
  7.     int length, max = 0, result;
  8.     int record[MAX];

  9.     record[0] = 0;
  10.     record[1] = 1;
  11.     record[2] = 2;

  12.     for(num = 3; num < MAX; num++)
  13.     {
  14.         a = num;
  15.         length = 0;

  16.         while(a != 1)
  17.         {
  18.             if(a < num)
  19.             {
  20.                 length += record[a];
  21.                 break;
  22.             }
  23.             if(a % 2)
  24.             {
  25.                 a = 3 * a + 1;
  26.             }
  27.             else
  28.             {
  29.                 a /= 2;
  30.             }
  31.             length++;
  32.         }
  33.         record[num] = length;

  34.         if(length > max)
  35.         {
  36.             max = length;
  37.             result = num;
  38.         }
  39.     }

  40.     printf("%d-->%d\n", result, max);

  41.     return 0;
  42. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-4-2 19:01:50 | 显示全部楼层
本帖最后由 JonTargaryen 于 2017-4-2 19:04 编辑
JonTargaryen 发表于 2017-4-2 18:52
你这个好棒!手动点赞!C语言秒出结果。

  1. def main():
  2.     record = [0, 1, 2]
  3.     max_length = 0

  4.     for num in range(3, 1000000):
  5.         a = num
  6.         length = 0

  7.         while(a != 1):
  8.             if a < num:
  9.                 length += record[a]
  10.                 break

  11.             if(a % 2):
  12.                 a = 3 * a + 1
  13.             else:
  14.                 a //= 2

  15.             length += 1

  16.         record.append(length)

  17.         if length > max_length:
  18.             max_length = length
  19.             result = num

  20.     print("%d-->%d" % (result, max_length))

  21. if __name__ == "__main__":
  22.     main()
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-5-1 03:11:04 | 显示全部楼层
  1. #include<stdio.h>

  2. long long collatz_len(long long);
  3. int main()
  4. {
  5.         long long max_len = 0;
  6.         long long num = 1;
  7.         for (long long i = 1;i < 1000000;i++) {
  8.                 if (max_len < collatz_len(i))
  9.                 {
  10.                         max_len = collatz_len(i);
  11.                         num = i;
  12.                 }
  13.         }
  14.         printf("%lld:%lld\n", num, max_len);
  15.         return 0;
  16. }

  17. long long collatz_len(long long x)
  18. {
  19.         long long count = 1;
  20.         while (x > 1)
  21.         {
  22.                 if (x % 2 == 0) {
  23.                         x /= 2;
  24.                 }
  25.                 else {
  26.                         x = x * 3 + 1;
  27.                 }
  28.                 count++;
  29.         }
  30.         return count;
  31. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-7-17 10:18:34 | 显示全部楼层
FlySelf 发表于 2017-2-7 11:24
执行结果:
[837799, 525]
程序执行了3.018928s。

自己想出来的和4楼一样,还是你这个快,
  1. if n < len(list_sequence):
  2.                 count += list_sequence[n]
复制代码


这真没想到,还把空闲的list_sequence[0]利用起来,感觉很老练
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-9-12 17:27:15 | 显示全部楼层

  1. maxlen,maxi = 0,0
  2. for i in range(1,int(1e6)):
  3.     count = 1
  4.     n = int(i/2 if not i%2 else 3*i+1)
  5.     while (n != 1):
  6.         count += 1
  7.         n = int(n/2 if not n%2 else 3*n+1)
  8.     if maxlen < count:
  9.         maxlen = count
  10.         maxi = i
  11.    

  12. print('{0} can produce the longest chain of {1}'.format(maxi, maxlen))
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-20 14:03

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表