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 = 9999999for 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 = 9999999999for 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 = Falsepentagonalist = set()i = 0while 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