[Project Euler]Problem 44

Pentagonal numbers are generated by the formula, Pn=n(3n1)/2. The first ten pentagonal numbers are:

1, 5, 12, 22, 35, 51, 70, 92, 117, 145, ...

It can be seen that P4 + P7 = 22 + 70 = 92 = P8. However, their difference, 70 22 = 48, is not pentagonal.

Find the pair of pentagonal numbers, Pj and Pk, for which their sum and difference is pentagonal and D = |Pk Pj| is minimised; what is the value of D?

 

这道题是一个关于五角数的题目,题目意思很明白,求解这么2个数的差的绝对值。这2个数的和和差都是五角数。题目看着比较简单,但是解起来还是有点费劲的。我试过了用范围分析等等各种方法但是开始都没解出来。

这是第一种版本

#This is version 1 using brute force.

#Version 1 can't find out the answer.



l = [i*(3*i-1)//2 for i in range(1, 100000)]

pd = 9999999



for i in range(9999):

    for j in range(i+1, 10000):

        if l[j] + l[i] in l[j:j+i] and l[j] - l[i] in l[j:j+i]:

            if l[j] - l[i] <= pd:

                pd = l[j] - l[i]

print(pd)

这个版本界定了一定的范围,但是其实更加加重了其线性搜索的计算量。虽然方法没错,但是计算不出来。

 

想了很久,想出了下面的改进的方法

l = [i*(3*i-1)//2 for i in range(1, 100000)]

s = set(l)

pd = 9999999999



for i in range(9999):

    for j in range(i+1, 10000):

        if l[j] + l[i] in s and l[j] - l[i] in s:

            if l[j] - l[i] < pd:

                pd = l[j] - l[i]

                

print(pd)

 

使用set来代替list,因为在使用身份操作符is 的时候,set效率会比list高出很多。在list上运用is操作符,会使用线性搜索。但是set里面,set是无序的,会有更优化的搜索方式。做了个简单的测试,is运行在同样的,成员数超过10000的时候,set的时间大概值需要list的1%。

 

记住一点:当对大的数据集进行身份操作符的时候,set绝对是一个不二的选择。set,主要用于membership, 还有删除重复成员。

 

即使运用了set, 上面的代码大概也还是需要23秒左右的时间。这题计算量有点大。

 

贴一个里面的一个人的code,比较容易明白,而且更快

solved = False

pentagonalist = set()

i = 0

while solved != True:

    i += 1

    pnum = int(i*(3*i-1)/2)

    pentagonalist.add(pnum)

    for num in pentagonalist:

        if pnum - num in pentagonalist and pnum - num*2 in pentagonalist:

            print("the answer is:", abs(num - (pnum - num)))

            solved = True

你可能感兴趣的:(project)