【題目】
有乙個機器按自然數序列的方式吐出球(1號球,2號球,3號球,……),你有乙個袋子,袋子最多只能裝下k個球,並且除袋子以外,你沒有更多的空間。
設計一種選擇方式,使得當機器吐出第n號球的時候(n>k),你袋子中的球數是k個,同時可以保證從1號球到n號球中的每乙個,被選進袋子的概率都是k
n\frac
nk。
舉乙個更具體的例子,有乙個只能裝下10個球的袋子。
當吐出100個球時,袋子裡有10個球,並且1~100號中的每乙個球被選中的概率都是10
100\frac
10010
;然後繼續吐球。
當吐出1000個球時,袋子裡有10個球,並且1~1000號中的每乙個球被選中的概率都是10
1000
\frac
100010
;繼續吐球。
當吐出i個球時,袋子裡有10個球,並且1~i號中的每乙個球被選中的概率都是10
i\frac
i10
,即吐球的同時,已經吐出的球被選中的概率也動態地變化。
保證第i次選球時,前i個球被選入袋中的概率相同為k
i\frac
ik(i<=k時,全為1)。
本質上為蓄水池演算法:動態變化等概率抽樣——每次抽樣(放球)時,每個球被抽中的概率都相等,但是每次這個概率數值會更改。
考慮第i次選球時,每個球放入袋中的概率為k
i\frac
ik;
第i個球只有這次放入袋中的機會,因此放入袋中的概率等於第i次選球概率,為k
i\frac
ik;
第i次在袋中的球被替換的概率為ki×
1k=1
i\frac \times \frac = \frac
ik×k1
=i1
;第i次在袋中的球被保留的概率為1−1
i=i−
1i
1-\frac = \frac
1−i1=
ii−1
觀察前i-1中的任意乙個球個球,第i次留在袋中的概率為
( kk
+1×k
+1k+
2×k+
2k+3
×...
×i−2
i−1×
i−1i
)=ki
(\frac \times \frac \times \frac \times ... \times \frac \times \frac) = \frac
(k+1k
×k+2
k+1
×k+3
k+2
×...
×i−1
i−2
×ii−
1)=
ik即袋中的球和第i個選球放入袋中的概率相同為k
i\frac
ik。
# 蓄水池演算法
import random
# uniform rand 1~max
defrand
(max):
return
int(random.random()*
max)+1
defgetknumsrand
(k, n)
:if n <
1or k <1:
return
none
res =[0
for i in
range
(min
(k, n))]
# 前k個球直接進入袋中
for i in
range(1
,len
(res)+1
):res[i -1]
= i # 從k+1個球起
for i in
range
(k +
1, n +1)
:# 第i個球以k/i概率替換袋中的球
if rand(i)
<= k:
res[rand(k)-1
]= i
return res
蓄水池演算法保證每次抽樣的公平性,對於第i次抽樣,每個樣本被抽中的概率相同——k
i\frac
ik,其中k為蓄水池容量。
最終每個樣本被抽中的概率為k
n\frac
nk,其中n為總樣本數。n可以不確定,換言之,可以一直抽樣,隨時喊停,也能保證抽樣的等概率。
因此在許多題目都有涉及。
放球遊戲B
校園裡在上活動課,red和blue兩位小朋友在玩一種遊戲,他倆在一排n個格仔裡,自左到右地輪流放小球,每個格仔只能放乙個小球。第乙個人只能放1個球,之後的人最多可以放前乙個人的兩倍數目的球,至少放1個球。最後面對沒有空格而不能放球的人為輸。現在red先走,問他有沒有必勝的策略?比如 n 4時,red...
遞推之合理放球
描述 n個各不相同球放入m個相同的盒子裡,球全部放完後,要求最後沒有空盒!求不同的放法總數。輸入一行兩個數n和m n表示球數,m表示盒子數 0 n 20 0 m 20 輸出不同且合理的放法總數 樣例輸入 3 2樣例輸出3提示 遞推第二類stirling數 解題思路 注意觀察題目要求,盒子是一樣的,球...
盒子放球的DP
ural1114 題目大意 有n個盒子,有紅色和藍色兩種顏色的球。紅球有a個,籃球有b個。現在隨意的向盒子裡放球,每個盒子可以放一種顏色的球,也可以放兩種顏色的球,也可以不放球。球不必全都放進盒子裡。問 總共有多少種方法。狀態dp i j k 表示向i個盒子裡放j個籃球和k個紅球的方案數目 狀態轉移...