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