原題如下:
有一個搶數(shù)游戲,其規(guī)則是兩人輪流報數(shù),每次可以報1 個,2 個,3 個,4個數(shù),但不許不報也不許多報,如果第一個人報1,2 或1,2,3,第二個人接著往下報,然后第一個人接著往下報,以此類推,那么第一個人第一次應(yīng)該報( )才可能穩(wěn)搶到1024.
1024,有點陡,我們先換一個小一點的數(shù)來分析:
搶“30”游戲,兩人從1開始輪流數(shù)數(shù),最少數(shù)1個數(shù),最多數(shù)3個數(shù),誰數(shù)到30誰贏,怎么數(shù)?
分析(假設(shè)其中一個人是我,且我想贏):
如果數(shù)到30就贏活孩,且每次只能數(shù)1-3個數(shù),那只需要數(shù)到26就可以了
當我數(shù)到26孩革,此時對方 加上1到3中的任何一個數(shù)都到不了30掂摔,反而只需要等對方數(shù)完后我再走一步就到30了,比如對方數(shù)2,就到28我再數(shù)個2就到30杨箭,對方數(shù)3寞焙,我數(shù)1就到30...
怎樣才能走到26呢,想一想:首先我們觀察一下每次報的數(shù):1互婿、2捣郊、3,這三個數(shù)能不能兩兩組合成一個固定的數(shù)慈参,我們發(fā)現(xiàn)呛牲,1+3=4, 2+2=4,所以這個固定的組合數(shù)就是 4 (自己去多寫幾個數(shù)來找找規(guī)律)
由此得方案:目標數(shù) 30 減去“最多數(shù) 3 個數(shù)”中的 3驮配,再減 1 得 26
如果 26 能被組合數(shù) 4 整除娘扩,則只需要對方先出,然后我每次出一個和對方相加和為 4 的數(shù)即可壮锻,最后我一定能數(shù)到 30
但很明顯此處的 26 不能被組合數(shù) 4 整除琐旁,所以:走第一步時一定要掌握主動權(quán),將 26 鈍化為可以被 4 整除的數(shù)猜绣,即 26 減去我第一步走的數(shù)后需要能被 4 整除灰殴。
故我要走第一步,且必須數(shù) 2 掰邢。26 - 2=24, 得到的 24 能被 4 整除
接下來只需要等對方出牺陶,(隨便出1-3中哪個數(shù)),我方只需要出一個和對方數(shù)字相加為 4 的數(shù)即可勝利辣之! (24/4=6 义图。即六輪后我就能數(shù)到30)
答案:
?我先數(shù),數(shù)2召烂;接下來我只需要數(shù)一個和對方相加為 4 的數(shù)即可我贏碱工、
接下來我們再來分析 1024 這道題:
方案如下:
1024-4-1 = 1019 即只需要拿到1019即可贏
組合數(shù)為:4+1 = 5
1019 除不盡組合數(shù) 5
故我先數(shù),數(shù)4, (1019-4=1015奏夫,這樣1015才能被5整除)
等對方數(shù)怕篷,然后我再數(shù)一個與對方的數(shù)和為5的數(shù)即可
接下來我們用 python 來實現(xiàn):
以下代碼直接復制即可運行(python3.7)
import random
def myFunc(n, stepper):
"""
:參數(shù) n: 目標數(shù)
:參數(shù) stepper: 步進范圍(可以走幾步的最大值)
:返回值: (flag,first_num,total_stepper)
第一個出還是第二個出:flag=1,第一個出;flag = 0第二個出
如果第一個出:第一次出多少 first_num
如果第二個出:出的數(shù)總和為多少 total_stepper
"""
total_stepper = stepper + 1 # 組合數(shù)
if n % total_stepper == 0: #能整除的情況
print("目標數(shù):{}酗昼,步進范圍:{}廊谓,組合數(shù):{}".format(n, stepper, total_stepper))
flag = 0 # 對方先出
return (flag, 0, total_stepper)
else:
v_num = n - stepper - 1 # 拿到v_num就一定能數(shù)到目標數(shù)
if v_num % total_stepper == 0: # v_num能被組合數(shù)整除的情況
flag = 0 # 對方先出
print("目標數(shù):{}, 步進范圍:{}麻削, 組合數(shù):{}, 是否第一個出:{}".format(n, stepper, total_stepper, flag))
return (flag, 0, total_stepper)
else:
flag = 1 # 我方先出
first_num = v_num % total_stepper # 我第一次數(shù)的數(shù)蒸痹,這個數(shù)將v_num鈍化為可以被組合數(shù)整除的數(shù)
print("目標數(shù):{}春弥, 步進范圍:{}, 組合數(shù):{}, 是否第一個出:{}, 出多少:{}".format(n, stepper, total_stepper, flag, first_num))
return (flag, first_num, total_stepper)
print(myFunc(1024,4))
運行結(jié)果截圖:
上面的代碼每一行都有注釋叠荠,結(jié)合著上面的分析來看就會很容易了匿沛。
最后的返回值為(是否先數(shù),先數(shù)多少榛鼎,組合數(shù)為多少)
這個函數(shù)可不是只能算1024這一道題哦逃呼,以后遇到這一類型的題,我們都可以將我們的的目標數(shù)和步進范圍輸入函數(shù)者娱,得到我們想要的答案抡笼。
------------ 啦啦啦啦。黄鳍。推姻。python 在手,媽媽再也不用擔心我的數(shù)學規(guī)律題了框沟! ------------
比如我們馬上就可以試一試其他的組合:
例1:
兩個人數(shù)數(shù)拾碌,誰先數(shù)到2048誰就勝利,每次可以數(shù)1-6中的任一個數(shù)街望。問誰會贏,怎么數(shù)弟跑?
運行結(jié)果為:
答案為:第一個人贏灾前。第一個人第一次數(shù)4,后面只需要數(shù)一個與對方的數(shù)和為 7 的數(shù)即可
例2:
兩個人數(shù)數(shù)孟辑,誰先數(shù)到 2019 誰就勝利哎甲,每次可以數(shù) 1-18 中的任一個數(shù)。問誰會贏饲嗽,怎么數(shù)炭玫?
運行結(jié)果為:
答案為:第一個人贏。第一個人第一次數(shù)5貌虾,后面只需要數(shù)一個與對方的數(shù)和為 19 的數(shù)即可
例3
兩個人數(shù)數(shù)吞加,誰先數(shù)到 2020 誰就勝利,每次可以數(shù) 1-9 中的任一個數(shù)尽狠。問誰會贏衔憨,怎么數(shù)?
運行結(jié)果為:
答案為:第二個人贏袄膏。第二個人只需要數(shù)一個與第一個人數(shù)的數(shù)和為 10 的數(shù)即可贏
這樣的結(jié)果是不是還不夠友好践图,那接下來我們再用 python 來模擬一下整個數(shù)數(shù)過程吧。
先來個溫柔一點的數(shù)到 30 就可以了沉馆。
程序代碼如下:
import random
def myFunc(n, stepper):
total_stepper = stepper + 1 # 組合數(shù)
if n % total_stepper == 0: #能整除的情況
flag = 0 # 對方先出
return (flag, 0, total_stepper)
else:
v_num = n - stepper - 1 # 拿到v_num就一定能數(shù)到目標數(shù)
if v_num % total_stepper == 0: # v_num能被組合數(shù)整除的情況
flag = 0 # 對方先出
return (flag, 0, total_stepper)
else:
flag = 1 # 我方先出
first_num = v_num % total_stepper # 我第一次數(shù)的數(shù)码党,這個數(shù)將v_num鈍化為可以被組合數(shù)整除的數(shù)
return (flag, first_num, total_stepper)
def myTest(n, stepper):
flag, first_num, total_stepper = myFunc(n, stepper) #調(diào)用myFunc函數(shù)得到:是否先數(shù)德崭、第一步數(shù)多少、組合數(shù)
print((flag, first_num, total_stepper))
i = 1 # 設(shè)定參照數(shù)
cnt = 0 # 數(shù)數(shù)容器
while True:
if flag == 1 and i == 1:
data = first_num
people = "我"
elif flag == i % 2 and i != 1:
people = "我"
data = total_stepper - data
else:
people = "碼小易"
data = random.randint(1, total_stepper-1)
cnt += data
print("{}第{}次出:{}".format(people, i, data))
if cnt == n:
break
i += 1
if __name__ == "__main__":
myTest(30, 3)
運行結(jié)果截圖:
以上即將數(shù)數(shù)的全過程模擬得清清楚楚了揖盘,怎么樣眉厨,現(xiàn)在來試試1024吧!
例4:
數(shù)到1024贏扣讼,每次數(shù)1-4中的一個數(shù):
??經(jīng)過以上兩個程序缺猛,是不是覺得 python 已經(jīng)把這道乃至于這一類磨人的數(shù)學題都梳理得服服帖帖的了呢,以后再遇到同樣的數(shù)學難題椭符,大家一定不要忘了用我們的 python 來實現(xiàn)荔燎,寫幾行代碼不僅能解決一道繞半天都繞不出來的題,還能直接搞定一個類型的數(shù)學題销钝。
??接下來就等著接收來自班里其他同學膜拜的眼神吧有咨!
??筆者會不定時的更新一些跟python相關(guān)又和數(shù)學相關(guān)的一些有趣的程序,喜歡就關(guān)注我吧蒸健。
特別警示:本文為作者原創(chuàng)作品座享,禁止不經(jīng)過本人同意就將其轉(zhuǎn)載用于商業(yè)用途,否則將予以追究似忧。出于學習分享轉(zhuǎn)載請附上出處鏈接渣叛,謝謝!