今天,在某Python群里,看到有一個問題,看似簡單,其實挺難的。題目如下:
小易總是感覺饑餓,所以作為章魚的小易經(jīng)常出去尋找貝殼吃。
最開始,小易在一個初始位置x_0。
對于小易所處的當(dāng)前位置x,它只能通過神秘的力量移動到4x+3或者8x+7。
因為使用神秘力量要耗費太多的體力,所以它只能使用神秘力量最多100,000次。貝殼總生長在能被1,000,000,007整除的位置(比如:位置0,位置1,000,000,007,位置2,000,000,014等)。
小易需要你幫忙計算最少需要使用多少次神秘力量就能吃到貝殼。
分析
設(shè)小易當(dāng)前位置為x_n,使用神秘力量移動以后的位置為x_(n+1)
兩個步長函數(shù)
首先對這兩個步長函數(shù)作一下變形:
由此可得
在看下面的分析之前,需要理解一個知識,這里簡單舉例說明
第一種走法:
4x+3,8x+7,4x+3
第二種走法:
4x+3,4x+3,8x+7
是完全一樣的,
這里我想說明的是,從初始位置開始,小易到達的最終位置只跟4x+3的次數(shù)和8x+7的次數(shù)有關(guān)系,與先走哪個沒有關(guān)系
假設(shè)小易到達目標(biāo)位置
所需的4x+3的次數(shù)為m次,此時到達的位置為x_m
所需的8x+7的次數(shù)為n次,此時的位置為目標(biāo)位置x_(m+n)
將上述兩個式子寫成一個
由此可知,4x+3所需次數(shù)m,8x+7所需次數(shù)n,初始位置x_0,最終位置x_(m+n)滿足如下關(guān)系
m 為4x+3的次數(shù), n 為8x+7的次數(shù), x_0 為初始位置,x_(m+n)為最終的目標(biāo)位置
而且由題目中的條件,小易應(yīng)該用最少的次數(shù),因此綜合上述分析,本題實際為如下的最優(yōu)化問題
由上述的分析,可知
只有當(dāng)該值為一個 整數(shù),即
(x_(m + n) + 1) / (x_0 + 1) = 2的某個指數(shù)冪
的時候,小易才可以從初始位置,到達目標(biāo)位置,否則永遠不可能到達。因此這也是題目中設(shè)置一個給定次數(shù)100000,判定程序結(jié)束的條件。
至此,從數(shù)學(xué)的角度本題已經(jīng)分析完了,剩下的就是 擼代碼。
import random
from math import log
import re
x0 = random.randint(1, 1000000006)
x0 = 125000000
k = 1
target = 1000000007
def get_m_n(sum, k):
m_n = []
m_max = sum // 2
n_max = sum // 3
min_c = m_max + n_max
for n in range(n_max + 1):
m = (sum - 3 * n) // 2
if 2 * m + 3 * n == sum:
if m + n <= min_c:
m_n.append((m, n))
min_c = m + n
# print(m_n)
print(f'初始位置為:{x0},目標(biāo)位置為:{k}倍距離,{k * target}')
print(f'最少次數(shù)為:{min_c}')
for i, j in m_n:
print(f'4x+3走{i}次,8x+7走{j}次')
while 1:
t = k * target
sum = log((t + 1) / (x0 + 1), 2)
# print(sum)
if sum >= 2.0 and re.findall('\d+\.0$', str(sum)):
get_m_n(int(sum), k)
break
elif k == 100000:
print('沒有找到')
break
k += 1