1. 程式人生 > >神奇的e 死理性派的數學模型:拒絕掉前面37%=1/e的人(marriage problem)

神奇的e 死理性派的數學模型:拒絕掉前面37%=1/e的人(marriage problem)

在每期《非誠勿擾》節目上,面對一位位男嘉賓,24 位單身女生要做出不止一次“艱難的決定”:到底要不要繼續亮燈?把燈滅掉意味著放棄了這一次機會,繼續亮燈則有可能結束節目之旅,放棄了未來更多的選擇。

在現實中,面對男生們前仆後繼的表白,MM 們也少不了這樣的糾結。如果遇到了一個優秀的男生,應該接受還是拒絕呢?如果接受了他,萬一下一個更好的話那可就虧大了;可如果為此而拒絕掉一個又一個好男人,也會面對著“過了這個村就沒這個店”的風險。說不定白馬王子們都已經擦肩而過,到最後就只剩下了猥瑣男了,當初的拒絕明顯得不償失。

由於沒人能知道真正的緣分何時到來,沒人能知道下一個來求愛的男生會是什麼樣子,接受表白的時機早晚實在很難決定。怎麼辦?去向《非誠勿擾》的黃菡老師和樂嘉老師請教一下?其實你還可以向尤拉老師請教一下。你沒聽錯。大數學家尤拉對一個神祕的數學常數 e ≈ 2.718 深有研究,這個數字和“拒人問題”竟然有著直接的聯絡。
“拒人問題”的數學模型為了便於我們分析,讓我們把生活中各種複雜糾紛的戀愛故事抽象成一個簡單的數學過程。假設根據過去的經驗,MM 可以確定出今後將會遇到的男生個數,比如說 15 個、30 個或者 50 個。不妨把男生的總人數設為 n。這 n 個男生將會以一個隨機的順序排著隊依次前來表白。每次被表白後,MM 都只有兩種選擇:接受這個男生,結束這場“徵婚遊戲”,和他永遠幸福地生活在一起;或者拒絕這個男生,繼續考慮下一個表白者。我們不考慮 MM 腳踏兩隻船的情況,也不考慮和被拒男生破鏡重圓的可能。最後,男人有好有壞,我們不妨假設 MM 心裡會給男生們的優劣排出個名次來。
聰明的 MM 會想到一個好辦法:先和前面幾個男生玩玩,試試水深;大致摸清了男生們的底細後,再開始認真考慮,和第一個比之前所有人都要好的男生髮展關係。從數學模型上說,就是先拒掉前面 k 個人,不管這些人有多好;然後從第 k+1 個人開始,一旦看到比之前所有人都要好的人,就毫不猶豫地選擇他。不難看出,k 的取值很講究,太小了達不到試的效果,太大了又會導致真正可選的餘地不多了。這就變成了一個純數學問題:在男生總數 n 已知的情況下,當 k 等於何值時,按上述策略選中最佳男生的概率最大?

如何求出最優的 k 值?對於某個固定的 k,如果最適合的人出現在了第 i 個位置(k < i ≤ n),要想讓他有幸正好被 MM 選中,就必須得滿足前 i-1 個人中的最好的人在前 k 個人裡如果此人出現在第 [k+1, i-1] 之間,則 MM 會優選選擇該 GG,而會錯失 Mr. Right, 也即是第 i 個人,),這有 k/(i-1) 的可能。考慮所有可能的 i,我們便得到了試探前 k 個男生之後能選中最佳男生的總概率 P(k):

P(k)=i=k+1n1nki1=kni=k+1n1i1
1n表示最合適的人出現在第 i 個位置的概率.
用 x 來表示 k/n 的值,並且假設 n 充分大,則上述公式可以寫成:
P
(k)=x1x1tdt=xlnx

對 -x · ln x 求導,並令這個導數為 0,可以解出 x 的最優值,它就是尤拉研究的神祕常數的倒數—— 1/e !

也就是說,如果你預計求愛者有 n 個人,你應該先拒絕掉前 n/e 個人,靜候下一個比這些人都好的人。假設你一共會遇到大概 30 個求愛者,就應該拒絕掉前 30/e ≈ 30/2.718 ≈ 11 個求愛者,然後從第 12 個求愛者開始,一旦發現比前面 11 個求愛者都好的人,就果斷接受他。由於 1/e 大約等於 37%,因此這條愛情大法也叫做 37% 法則。
不過,37% 法則有一個小問題:如果最佳人選本來就在這 37% 的人裡面,錯過這 37% 的人之後,她就再也碰不上更好的了。但在遊戲過程中,她並不知道最佳人選已經被拒,因此她會一直痴痴地等待。也就是說,MM 將會有 37% 的概率“失敗退場”,或者以被迫選擇最後一名求愛者的結局而告終。

**37% 法則“實測”!**37% 法則的效果究竟如何呢?我們在計算機上編寫程式模擬了當 n = 30 時利用 37% 法則進行選擇的過程(如果 MM 始終未接受求愛者,則自動選擇最後一名求愛者)。編號越小的男生越次,編號為 30 的男生則表示最佳選擇。程式執行 10000 次之後,竟然有大約 4000 次選中最佳男生,可見 37% 法則確實有效啊。


import random

n, k = 30, 12
N = 10000

cnt = 0
for _ in range(N):
    GG = [random.random() for _ in range(n)]
    for i in range(k-1, n):
        if GG[i] > max(GG[:k-1]):
            choice = i
            if GG[choice] == max(GG):
                cnt += 1
            break
print(cnt)

這個問題由數學家 Merrill M. Flood 在 1949 首次提出,這個問題被他取名為“未婚妻問題”http://en.wikipedia.org/wiki/Secretary_problem。這個問題的精妙之處在於,在微積分界叱吒風雲的自然底數 e,竟也出人意料地出現在了這個看似與它毫不相關的問題中。不知道此問題發表後,Geek 男女間會不會多了一種分手的理由:不好意思,你是那 37% 的人⋯⋯