zoukankan      html  css  js  c++  java
  • Python练习题 040:Project Euler 012:有超过500个因子的三角形数

    本题来自 Project Euler 第12题:https://projecteuler.net/problem=12

    # Project Euler: Problem 12: Highly divisible triangular number
    # The sequence of triangle numbers is generated by adding the natural numbers.
    # So the 7th triangle number would be 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28.
    # The first ten terms would be:
    # 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...
    # Let us list the factors of the first seven triangle numbers:
    # 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
    # We can see that 28 is the first triangle number to have over five divisors.
    # What is the value of the first triangle number to have over five hundred divisors?
    # Answer: 76576500
    
    import time
    startTime = time.clock()
    
    def f(x):
        c = 0
        for i in range(1,int(x**.5)+1):
            if x%i == 0:
                c += 1
        if float(int(x**.5)) == x**.5:
            return (c*2-1)
        else:
            return(c*2)
    
    triNumber = 1
    natNumber = 1
    while f(triNumber) < 500:
        natNumber += 1
        triNumber += natNumber
        f(triNumber)
    print(triNumber)
    
    print('Time used: %.2d' % (time.clock() - startTime))
    

    所谓“三角形数”,指的是自然数相加后的和,第n个三角形数即是从1开始的n个自然数相加后的和。例如:第5个三角形数就是 1+2+3+4+5=15。而15这个数字拥有的所有因子为:1、3、5、15 这四个数字。本题求解首个拥有 500 个因子的三角形数。

    一开始我是这么想的:先写一个函数,用来把任意三角形数的所有因子放进列表 lst 里。之后再写一个 while 循环函数,只要 len(lst) 不超过 500,就不停计算下一个更大的三角形数,直到 len(lst) 超过 500,这个三角形数即为题解。写完了,计算拥有超过 50 个因子的倒还可以,但 500?反正运行了半天也没算出来:判断是否为因子的这几行代码太费时间了。

    于是又求助网络(来源网页找不着了,刚才电脑死了一次机),发现有这么一个思路:其实,判断三角形数 x 有多少个因子,根本不需要判断 range(1, x+1) 这么多次,而是大概只需要判断 range(1, int(x**.5)+1) 次,然后把这个次数乘以 2 就行。唯一例外就是:如果 x 开根号后仍是整数,那么次数乘2之后,还得减掉1才行。为什么呢?算法啥的我是不太懂,但观察一下还是能观察出来的:

    比如:28(第7个三角形数)的因子是:1、2、4、7、14、28,而根号28(5.3)正好就在4、7中间,处于所有因子的中间,因此只要判断 range(1,6) 就可以得出1/2的次数,之后乘2就可以了。

    但是:36(第8个三角形数)的因子是:1、2、3、4、6、9、12、18、36,而根号36正好是6,也正好处于所有因子的中间,但6是其中一个因子,不像上例中的5.3,并非因子。因此,如果判断 range(1,7) 再乘以2,就会多算进一个数字(即因子6被乘2,多算了1个)。因此,在这种开根号正好是整数的情况下,必须把总次数减掉1才行。

    如此一开根号,我这破电脑也能在12秒左右算出答案。撒花~~~~~~

  • 相关阅读:
    DS博客作业03--树
    DS博客作业02--栈和队列
    数据结构——线性表
    结构体
    C博客作业05--指针
    C语言博客作业04--数组
    面向对象设计大作业第二阶段:图书馆系统
    Java程序设计-有理数类的设计
    DS博客作业05-查找
    DS博客作业04-图
  • 原文地址:https://www.cnblogs.com/iderek/p/6016254.html
Copyright © 2011-2022 走看看