0
点赞
收藏
分享

微信扫一扫

算法:概率数学相关题目

幸福的无所谓 2022-05-02 阅读 62

随机数发生器。

给定一个随机数发生器构造另一个随机数发生器;
给定一个随机数发生器对数列进行采样。

  1. 给定一个等概率随机产生1~5的随机函数f()。除此之外,不能使用任何额外的随机机制,请实现等概率随机产生1 ~ 7的随机函数。
    解答:将f()通过乘和加的运算构造自然数序列。
    步骤1 g() = f()-1 -> 0,1,2,3,4
    步骤2 g()*5 + g() -> 0,1,2,3,4,5,6,7,…,24
    步骤3 若步骤2产生的数大于20,重复步骤2;若小于等于20,%7,即可等概率产生0-6
    步骤4 步骤3结果+1.
def randomInt5():
    # 生成1-5的随机函数
    return int(random.random()*5) + 1
def randomInt7():
    res = (randomInt5()-1)*5 + (randomInt5()-1)  #0,1,2,..,24
    if res <= 20:
        return res % 7
    else:
        return randomInt7()
if __name__ == "__main__":
    dic  = {}
    for i in range(100000):
        res = randomInt7()
        if res not in dic:
            dic[res] = 1
        else:
            dic[res] += 1
    print(dic)
  1. 给定一个以p概率生成0,以1-p概率产生1的随机函数f(),p是固定的值,但是你并不知道是多少。除此之外也不能使用任何额外的随机机制,请用f()实现等概率随机产生0和1的随机函数。
    解答:虽然p未知,但是连续调用f()2次,产生01和10序列的概率均为p(1-p)。基于这点可以等概率随机产生0和1。
import random
def f(p:float=0.3):
    # 以p的概率产生0,以1-p的概率产生1
    if random.random()<p:
        return 0
    else:
        return 1
def generate(p:float=0.3):
    first = f(p)
    second = f(p)
    if first==0 and second==1:
        return 0
    elif first==1 and second==0:
        return 1
    else:
        return generate(p)
if __name__ == "__main__":
    cnt = 0
    for i in range(500000):
        if generate()==1:
            cnt += 1
    print(cnt)

3 假设函数f()等概率随机返回一个在[0,1)范围上的浮点数,那么我们知道,在[0,x)区间上的数出现的概率为x(0<x<=1)。给定一个大于0的整数k,并且可以使用f()函数,请实现一个函数依然返回在[0,1)范围上的数,但是在[0,x)区间上的数出现的概率为x的k次方。
解答:调用K次f(),返回较大的数即可。

def randomK(k:int=3):
    max_value = -1
    for i in range(k):
        tmp = random.random()
        max_value  = max(max_value, tmp)
    return max_value

if __name__ == '__main__':
    for i in range(100):
        print(randomK())
  1. 给定一个长度为 N 且没有重复元素的数组 arr 和一个整数 M,实现函数等概率随机打印 arr 中的 M 个数。
    解答:有很多思路去实现题中的"随机",这里介绍一种代价较低的方案。
    步骤1:在0-N-1中随机得到一个index,将index的值输出,并与数组最后一个位置交换
    步骤2:在0-N-2中随机得到一个index,将index的值输出,并与数组倒数第二个位置交换。
    如此操作,直到输出M个数。
def selectM(arr, m:int=5):
    n = len(arr)
    for i in range(m):
        idx = int(random.random() * (n-i)) - 1
        print(arr[idx])
        arr[idx], arr[n-i-1] = arr[n-i-1], arr[idx]

if __name__ == '__main__':
    arr = [1,2,3,4,5,6,7,8,9,10]
    selectM(arr)
    print(arr)
  1. 有一个机器按自然数序列的方式吐出球,1号球,2号球,3号球等等。你有一个袋子,袋子里最多只能装下K个球,并且除袋子以外,你没有更多的空间,一个球一旦扔掉,就再也不可拿回。设计一种选择方式,使得当机器吐出第N号球的时候,你袋子中的球数是K个,同时可以保证从1号球到N号球中的每一个,被选进袋子的概率都是K/N
    更具体的例子:
    有一个只能装下10个球的袋子,当吐出100个球时,袋子里有10 球,并且1 ~ 100号中的每一个球被选中的概率都是10/100。
    然后继续吐球,当吐出1000个球时,袋子里有 10 个球,并且1 ~ 1000号中的每一个球被选中的概率都是10/1000。
    继续吐球,当吐出i个球时,袋子里有10个球,并且1 ~ i号中的每一个球被选中的概率都是10/i。也就是随着N的变化,1~N号球被选中的概率动态变化成k/N。
    解答:蓄水池抽样算法
    基本过程
    步骤1)处理1-K号球时,直接放进袋子里;
    步骤2)处理第 i 号球时,以 k/i 的概率决定是否将第 i 号球放进袋子里。如果不决定将第 i 号球放进袋子,直接扔掉第 i 号球;如果决定将第 i 号球放进袋子,
    那么就从袋子里的 k 个球中随机扔掉一个,然后把第 i 号球放入袋子。
    步骤3)处理第 i+1 号球时, 重复步骤1或步骤2。
    证明
    情形一) 假设第 i 号球被选中,并且 1 <= i <= k,那么第 i 号球最终留在袋子中的概率是 K/N。
    在选 k+1 号球之前,第i号球留在袋子中的概率为1。
    在选 k+1号球时,只有决定将k+1号球放入袋子,同时在袋子中的第i号球被随机选中并决定扔掉,这两个事件同时发生时第i号球才会被淘汰,第i号球被淘汰的概率是 k k + 1 × 1 k = 1 k + 1 \frac{k}{k+1} \times \frac{1}{k} = \frac{1}{k+1} k+1k×k1=k+11,所以第i号球留下来的概率是是 k k + 1 \frac{k}{k+1} k+1k
    在选 k+2 号球时,只有决定将 k+2 号球放入袋子,同时在袋子中的第i号球被随机选中并决定扔掉,这两个事件同时发生时第i号球才会被淘汰,第i号球被淘汰的概率是 k k + 2 × 1 k = 1 k + 2 \frac{k}{k+2}\times\frac{1}{k}=\frac{1}{k+2} k+2k×k1=k+21,所以第i号球留下的概率是 k + 1 k + 2 \frac{k+1}{k+2} k+2k+1
    依次类推,在选N号球时,从1号到N号的全部过程中,第i号球最终留在袋子中的概率是
    k k + 1 × k + 1 k + 2 ∗ k + 2 k + 3 ∗ k + 3 k + 4 . . . . ∗ N − 1 N = k N \frac{k}{k+1}\times\frac{k+1}{k+2}∗\frac{k+2}{k+3}∗\frac{k+3}{k+4}....∗\frac{N−1}{N}=\frac{k}{N} k+1k×k+2k+1k+3k+2k+4k+3....NN1=Nk
    情形二) 假设第i号球被选中,并且 k < i <= N。那么第 i 号球最终留在袋子中的概率是 K/N。
    第 i 号球被选中留下的概率是 k i \frac{k}{i} ik
    第 i+1 号球被选中,并且i号球淘汰的概率是 k i + 1 ∗ 1 k = 1 i + 1 \frac{k}{i+1} * \frac{1}{k} = \frac{1}{i+1} i+1kk1=i+11, 第 i 号球留下的概率是 i i + 1 \frac{i}{i+1} i+1i
    依次类推,在选N号球时,第i号球最终留在袋子中的概率是:
    k i ∗ i i + 1 ∗ i + 1 i + 2 . . . ∗ N − 1 N = k N \frac{k}{i} * \frac{i}{i+1} * \frac{i+1}{i+2}... * \frac{N-1}{N} = \frac{k}{N} iki+1ii+2i+1...NN1=Nk

基本概率题

  1. 三只蚂蚁从正三角形的三个定点沿着边移动,速度是相同的,它们碰头的概率是多少?
    解答:只要两个碰头就算碰头。答案是 3 4 \frac{3}{4} 43
  2. 假设某地区重男轻女,一个家庭如果生出一个女孩就一直生,知道生出男孩就停止生育。假设一胎只出生一个孩子,问时间足够长后,男女比例是会变为多少?
    解答:1:1
  3. 8只球队,3个强队,其余都是弱队。随机把它们分成4组比赛,每组两个队。问两强相遇的概率是多大?
    解答
    8只球队的分组数:
    f ( 8 ) = C 8 2 ∗ C 6 2 ∗ C 4 2 ∗ C 2 2 4 ∗ 3 ∗ 2 ∗ 1 f(8) = \frac{C_{8}^{2}*C_{6}^{2}*C_{4}^{2}*C_{2}^{2}}{4*3*2*1} f(8)=4321C82C62C42C22
    8只球队中,让3个强队中两强一组的分组数: C 3 2 C_{3}^2 C32,其他6队随机分组:
    f ( 6 ) = C 6 2 ∗ C 4 2 ∗ C 2 2 3 ∗ 2 ∗ 1 f(6) = \frac{C_{6}^{2}*C_{4}^{2}*C_{2}^{2}}{3*2*1} f(6)=321C62C42C22
    8只球队中,两强相遇概率:
    f ( 6 ) ∗ C 3 2 f ( 8 ) = 3 7 \frac{f(6)*C_{3}^2}{f(8)} = \frac{3}{7} f(8)f(6)C32=73
    注:不能直接 C 8 2 ∗ C 6 2 ∗ C 4 2 ∗ C 2 2 C_{8}^{2}*C_{6}^{2}*C_{4}^{2}*C_{2}^{2} C82C62C42C22计算分组数的原因是会将分组重复计算。
    参考:
    链接1
    链接2
举报

相关推荐

0 条评论