鱼C论坛

 找回密码
 立即注册
查看: 3975|回复: 12

[技术交流] 小练习:20160503 第一个拥有超过500个约数的三角形数是多少?

[复制链接]
发表于 2016-5-3 08:39:15 | 显示全部楼层 |阅读模式

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

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

x
本帖最后由 冬雪雪冬 于 2016-5-10 12:24 编辑

从现在开始我们要开展一批欧拉计划的习题练习。
其实在我们论坛中已有欧拉计划的板块,可能有些鱼油还没注意到。
什么是欧拉计划:http://bbs.fishc.com/thread-60405-1-1.html
我们欧拉板块现已给出了81道题,这批练习将从欧拉计划中选题。其实用python语言完成有很多的优势,可以更简洁更方便的实现。
如果大家有兴趣也可浏览欧拉的英文网站:https://projecteuler.net/archives
这里已经有了500余题,并且你每做对一题,就可以下载到参考答案的pdf文件,看看你的实现方法与参考答案有什么不同,以利于迅速提高自己的水平。


                               
登录/注册后可看大图

好了言归正传,我们开始做小练习。




题目要求:
以python语言完成,如果是python2请注明。
程序以代码文字格式发帖。
题目比较简单,注重程序效率和创意。
答题在5.10 10:00前完成,其后将公开大家的答案,并评比成绩。

另程序和答案可以在网上搜到,希望大家独立完成。


题目:

三角形数序列是由对自然数的连加构造而成的。所以第七个三角形数是 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28. 那么三角形数序列中的前十个是:

1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...

下面我们列出前七个三角形数的约数:

1: 1
3: 1,3
6: 1,2,3,6
10: 1,2,5,10
15: 1,3,5,15
21: 1,3,7,21
28: 1,2,4,7,14,28
可以看出 28 是第一个拥有超过 5 个约数的三角形数。

那么第一个拥有超过 500 个约数的三角形数是多少?



奖励:
对所有完成程序并得出正确答案的将给予加分奖励,优秀的将额外加分。
在完成一批题目后,将根据每期的完成情况总评评出最佳,会有神秘大奖。

本帖被以下淘专辑推荐:

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

使用道具 举报

发表于 2016-5-3 22:54:15 | 显示全部楼层
  1. import math

  2. def divisor(n):
  3.     result=[]
  4.     t=0
  5.     for i in range(1,int(math.sqrt(n))+1):
  6.         if n%i==0:
  7.             result.append(i)
  8.     if math.sqrt(n)==int(math.sqrt(n)):
  9.         t=1
  10.     return len(result)*2-t
  11.    
  12. def trinum(n):
  13.     result=0
  14.     for i in range(1,n+1):
  15.         result+=i
  16.     return result

  17. i=1
  18. stop=False
  19. while 1:
  20.     for j in [i+2,i+3]:
  21.         num=trinum(j)
  22.         n=divisor(num)
  23.         if n>500:              
  24.             print('第一个拥有超过500个约数的三角形数是:\n第%d个三角形数%d,共有%d个约数'%(j,num,n))
  25.             stop=True
  26.     if stop:break      
  27.     i+=4
  28.    
  29.    
复制代码

评分

参与人数 1荣誉 +5 鱼币 +5 收起 理由
冬雪雪冬 + 5 + 5 热爱鱼C^_^

查看全部评分

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

使用道具 举报

发表于 2016-5-3 23:24:49 | 显示全部楼层
本帖最后由 EggyBruch 于 2016-5-5 19:06 编辑
  1. import time
  2. def tri_num(app_num):
  3.     startTime = time.time()
  4.     n = 1
  5.     sum = 0
  6.     count = 0
  7.     while count <= app_num:
  8.         sum = 0
  9.         count = 0
  10.         for i  in range (1,n+1):
  11.             sum += i
  12.             triangle = sum
  13.         divisor = []
  14.         amount = 0
  15.         for x in range(1,triangle+1):
  16.             if triangle % x == 0:
  17.                 divisor.append(x)
  18.                 amount += 1
  19.                 length = len(divisor)
  20.                 if (divisor[length - 2]*divisor[length-1] == triangle or
  21.                     divisor[length - 1]*divisor[length-1] == triangle):
  22.                     break
  23.         count = 2*(amount - 1)
  24.         n += 1
  25.     print('第一个拥有超过%d个约数的三角形数为:'%(app_num),sum)
  26.     print('read: %.3fs '%(time.time()-startTime))

复制代码

第一个拥有超过500个约数的三角形数为: 76576500
read: 23.064s

评分

参与人数 1荣誉 +5 鱼币 +5 收起 理由
冬雪雪冬 + 5 + 5 热爱鱼C^_^

查看全部评分

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

使用道具 举报

发表于 2016-5-4 21:32:10 | 显示全部楼层
本帖最后由 老忘 于 2016-5-10 21:48 编辑
  1. __author__ = '老忘'
  2. #-*- coding: UTF-8 -*-

  3. def getChildren(num):
  4.     #递归分解因式
  5.     import math
  6.     isZhishu = True
  7.     i = 2
  8.     square = int(math.sqrt(num)) + 1
  9.     while i <= square:
  10.         if num % i == 0:
  11.             list_submultiple.append(i)
  12.             isZhishu = False
  13.             getChildren(num / i)
  14.             i += 1
  15.             break
  16.         i += 1
  17.     if isZhishu:
  18.         list_submultiple.append(int(num))


  19. n=1
  20. while 1:
  21.     m=n*(n+1)/2
  22.     list_submultiple=[]

  23.     getChildren(m)  #分解并存入 list_submultiple
  24.     list_submultiple_only=set(list_submultiple)#去重存入list_submultiple_only

  25. #约数个数为每个质因数的指数加1并相乘
  26.     s=1
  27.     z=0
  28.     for val_lso in list_submultiple_only:
  29.         z=int(list_submultiple.count(val_lso))+1
  30.         s *=z

  31.     if s>500:
  32.         print(int(m))
  33.         break
  34.     else:
  35.         n +=1
复制代码

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
冬雪雪冬 + 3 + 3 热爱鱼C^_^

查看全部评分

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

使用道具 举报

发表于 2016-5-4 21:56:11 | 显示全部楼层
严重支持
  1. def factorNumber(num):
  2.     result = 0
  3.     i = 1
  4.     while True:
  5.         if num%i==0:
  6.             result += 1
  7.             if num/i!=i:
  8.                 result += 1
  9.         i += 1
  10.         if i>num**0.5:
  11.             break
  12.     return result

  13. def findTriNum(factorNum):
  14.     i = 1
  15.     triNum = 0
  16.     while True:
  17.         triNum += i
  18.         if factorNumber(triNum)>factorNum:
  19.             break
  20.         i += 1
  21.     return triNum

  22. print(findTriNum(500))
复制代码

运行结果
  1. >>>
  2. 76576500
  3. >>>
复制代码

评分

参与人数 1荣誉 +5 鱼币 +5 收起 理由
冬雪雪冬 + 5 + 5 热爱鱼C^_^

查看全部评分

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

使用道具 举报

发表于 2016-5-5 10:37:09 | 显示全部楼层
本帖最后由 bacon6581 于 2016-5-5 23:12 编辑

思路:
1.依次列举三角形数
2.取该三角形数的算术平方根
3.判断该算术平方根是否整数
4.判断该三角形数依次能被多少自然数整除,自然数范围为:range(2,算数平方根取整)
-----------------------------------------
说明:
1.任何自然数都能被1和其本身整除。所以约束直接2起步
2.如果自然数能被小于算数平方根的数整除,则必然存在有一个大于算数平方根的数 整除
   即:能被小于算数平方根的自然数整除,则必有2个约数
   如20能被2整除,则必然能被10整除;能被4整除,则必然能被5整除
3.如果该三角形数的算数平方根是整数,则只增加一个约数
   如9的算数平方根是3。则只会增加一个约数3。(3*3=9)
  1. from math import sqrt
  2. n=1
  3. num=1
  4. while True:
  5.     n=n+1
  6.     num=num+n
  7.     m=2
  8.     if int(sqrt(num))==sqrt(num):
  9.            m-=1
  10.     for i in range(2,int(sqrt(num))+1):
  11.         if num%i==0:
  12.             m=m+2
  13.     if m>500:
  14.         break
  15. print(n)
  16. print(num)
复制代码


结果如图:
第12375个三角形数
数值:76576500

无标题.jpg

评分

参与人数 1荣誉 +5 鱼币 +5 收起 理由
冬雪雪冬 + 5 + 5 热爱鱼C^_^

查看全部评分

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

使用道具 举报

发表于 2016-5-5 15:02:23 | 显示全部楼层
  1. import time
  2. begTime = time.clock()
  3. def prime(trianglenum):
  4.     divisor=[]
  5.     while trianglenum != 1:
  6.         for i in range(2,trianglenum+1):
  7.             if trianglenum % i == 0:
  8.                 trianglenum //= i
  9.                 divisor.append(i)
  10.                 break
  11.     return divisor
  12. num=1
  13. n=2
  14. while num <=500:
  15.     num=1
  16.     s1=sum(range(1,n))
  17.     n+=1
  18.     divisor=prime(s1)
  19.     a1=list(set(divisor))
  20.     for each in a1:
  21.         count1=divisor.count(each)
  22.         num*=(count1+1)
  23. print('因子',divisor)
  24. s1=1
  25. for each in divisor:
  26.     s1*=each
  27. print('三角数%d 有%d个约数' %(s1,num))
  28. print(time.clock() - begTime)
复制代码
  1. 因子 [2, 2, 3, 3, 5, 5, 5, 7, 11, 13, 17]
  2. 三角数76576500 有576个约数
  3. 5.7881082194113835
复制代码

评分

参与人数 1荣誉 +8 鱼币 +8 收起 理由
冬雪雪冬 + 8 + 8 热爱鱼C^_^

查看全部评分

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

使用道具 举报

发表于 2016-5-6 17:08:23 | 显示全部楼层
  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Fri May  6 09:34:52 2016

  4. @author:
  5. """
  6. #定义一个计算约数个数的函数
  7. def count_divisor(n):
  8.     t = int(n/2)
  9.     divisor_n=2
  10.     while t>1:
  11.         if n%t == 0:
  12.             t = t-1
  13.             divisor_n = divisor_n+1
  14.             #print(t,divisor_n)
  15.         else:
  16.             t = t-1
  17.             #print(t)
  18.     return(divisor_n)

  19. #定义一个产生三角形数的函数
  20. def delta(n):
  21.     sumn = 0
  22.     i=1   
  23.     while i<n:
  24.         sumn = sumn+i
  25.         i = i+1
  26.     return(sumn)
  27. #初始化,y是判断约数个数是否大于500的一个开关,C是三角形数的层数
  28. y=1
  29. c=1
  30. #从第一层三角形数开始,当约数个数是500时,则结束,打印;不是的时候层数加1

  31. while y>0:
  32.    number = delta(c)
  33.    divisor = count_divisor(number)
  34.    if divisor==500:
  35.        y=0
  36.        print("这个数是:%i"%number)
  37.        print("约数个数:%i"%divisor)
  38.    else:
  39.        c = c+1
  40.        print(c,number,divisor)
复制代码

这是笨办法

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
冬雪雪冬 + 3 + 3 热爱鱼C^_^

查看全部评分

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

使用道具 举报

发表于 2016-5-7 18:57:53 | 显示全部楼层
先实现功能,后续再改进;
  1. import time

  2. t_start = time.clock()
  3. # 统计因数个数
  4. def count_div(n):
  5.     if n==1:
  6.         return 1
  7.     if n==2:
  8.         return 2
  9.     div = []
  10.     while n>2:
  11.         for i in range(2,n+1):
  12.             if n%i == 0:
  13.                 div.append(i)
  14.                 n = int(n/i)
  15.                 break
  16.     cou_div = 1
  17.     for i in set(div):
  18.         cou_div *= div.count(i)+1
  19.     return cou_div

  20. # 确定搜索起始值
  21. idx = 2*3*5*7*11*14*17*19 #最小的有256个因数的数
  22. n = 100
  23. while sum(i for i in range(n+1)) < idx:
  24.     n += 1
  25. t = sum(i for i in range(n+1))
  26. while count_div(t)<500:
  27.     n += 1
  28.     t = sum(i for i in range(n+1))

  29. print('第一个拥有超过 500 个约数的三角形数是:%d'%t)
  30. print('用时%s秒'%str(time.clock()-t_start))
复制代码


答案是:
  1. 第一个拥有超过 500 个约数的三角形数是:76576500
  2. 用时6.540758731005951秒
复制代码

评分

参与人数 1荣誉 +5 鱼币 +5 收起 理由
冬雪雪冬 + 5 + 5 热爱鱼C^_^

查看全部评分

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

使用道具 举报

发表于 2016-5-7 21:48:39 | 显示全部楼层
本帖最后由 zooo 于 2016-5-10 15:26 编辑
  1. import time

  2. begTime = time.time()

  3. def find_num(num) :
  4.         mid = num/2
  5.         if mid != num//2:
  6.             return 0
  7.         counter = 0
  8.         n=1
  9.         while True:
  10.                 if num%n == 0 and n+1<mid:
  11.                         counter += 2
  12.                         mid = num//n
  13.                 n += 1        
  14.                 if n>mid:
  15.                         break
  16.                                 
  17.         return(counter)

  18. num =1
  19. n =2
  20. while True:
  21.         num +=n
  22.         n+=1
  23.         if find_num(num)>500:
  24.                 break

  25. print(num, time.time()-begTime)
复制代码


并行计算:2核电脑效率提高近一倍,电脑核心数量越多用时越短
并行模块下载地址:http://www.parallelpython.com/content/view/18/32/ sshot.jpg

代码:
  1. import time, pp

  2. begTime = time.time()

  3. def find_num(start, end) :
  4.         for index in range(start, end+1):
  5.                 num = 0.5*index*(index+1)
  6.                 mid = num/2
  7.                 if mid != num//2:
  8.                     continue
  9.                 counter = 0
  10.                 n=1
  11.                 while True:
  12.                         if num%n == 0 and n+1<mid:
  13.                                 counter += 2
  14.                                 mid = num//n
  15.                         n += 1        
  16.                         if n>mid:
  17.                                 break
  18.                 if counter > 500:
  19.                         return num
  20.         return 0

  21. start = 1
  22. end = 10000
  23. step = int((end - start)/128 + 1)#将区间分成128段

  24. job_server = pp.Server()

  25. stopFlag = 0

  26. while True:
  27.         res_list = []
  28.         for index in range(128):
  29.                 starti = start + index * step
  30.                 endi = min( start + index * (step+1), end )
  31.                 res_list.append(job_server.submit(find_num, (starti, endi)))

  32.         for fun in res_list:
  33.                 if fun():
  34.                         stopFlag = 1
  35.                         print(fun(), time.time()-begTime)
  36.                         break

  37.         if stopFlag:
  38.                 break
  39.         
  40.         start += 10000
  41.         end += 10000
复制代码

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
冬雪雪冬 + 3 + 3 热爱鱼C^_^

查看全部评分

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

使用道具 举报

发表于 2016-5-8 00:21:17 | 显示全部楼层
本帖最后由 挥舞乾坤 于 2016-5-11 09:18 编辑
  1. def fun(n):
  2.     r, i = 0, 0
  3.     while True:
  4.         i += 1
  5.         r += i
  6.         c = 0
  7.         if r % 2:
  8.             continue
  9.         for j in range(1,int(r **.5)+1):
  10.             if r % j == 0:
  11.                 c += 2
  12.         if c >= n:
  13.             return r
  14. print(fun(500))
复制代码

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
冬雪雪冬 + 3 + 3 热爱鱼C^_^

查看全部评分

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

使用道具 举报

发表于 2016-5-8 20:10:58 | 显示全部楼层
  1. max_Y =5     #  公约数   (计算130,用了40多秒,数越大,后面越慢)

  2. s = 10000000   # 三角形数
  3. h = 0
  4. for i in range(1,s+1):
  5.     h = h + i
  6.     Y = []
  7.     for i3 in range(1,h+1):
  8.         if(h % i3 == 0):
  9.             Y.append(i3)
  10.     #print(i,h,':',Y)
  11.     if( len(Y) > max_Y ):
  12.         print('这是第 %d 个三角形数'%i,'第一个拥有 %d 个公约数'%max_Y)
  13.         print(h,':',Y)
  14.         break
复制代码

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
冬雪雪冬 + 3 + 3 热爱鱼C^_^

查看全部评分

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

使用道具 举报

发表于 2016-5-10 12:08:13 | 显示全部楼层
楼主等我别开车
  1. def fi(su):
  2.     i=1
  3.     inte=0
  4.     while i*i<=su:
  5.         if(su%i==0):
  6.             inte+=2
  7.         i+=1
  8.     if (i-1)**2==su:
  9.         inte-=1
  10.     return inte
  11. mi=250**2
  12. c=0
  13. s=0
  14. inte=0
  15. while s<mi:
  16.     c+=1
  17.     s+=c
  18. while inte<500:
  19.     c+=1
  20.     s+=c
  21.     inte=fi(s)
  22.    
复制代码

12375

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
冬雪雪冬 + 3 + 3 热爱鱼C^_^

查看全部评分

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-23 21:16

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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