【周赛总结】第191场周赛——两个盒子中球的颜色数相同的概率

2020/05/31 ACE : 3/4 rank:322/3686
没有完全a完,早上的比赛没太睡醒,中间被罚了两次。比赛链接

还是重点讲解第四题吧,比赛时候没有a出来。

两个盒子中球的颜色数相同的概率

【周赛总结】第191场周赛——两个盒子中球的颜色数相同的概率_第1张图片
【周赛总结】第191场周赛——两个盒子中球的颜色数相同的概率_第2张图片

题目的翻译真的不是很好,是要求计算两个盒子里,a盒中颜色不同的球的种类和b盒中颜色不同的球的种类相同的概率。

一看就是排列组合题目,首先我们需要得到分母。可以考虑先作为完全不一样的球,计算全排列n!,然后在依次进行捆绑,同一个种类的球是不存在区别的,因此可以随便换位置。需要除以每个种类的球的个数的阶乘。得到的就是分母。对于这一系列的计算,称为可重复的排列数

然后是分子的计算,采用了枚举dfs的方法。按照球的种类进行搜索,每次对一种球进行划分,确定左侧放入几个球,右侧放入几个球。并且把左右盒子想象成了格子盒。这样在统计左右的不同类型球的时候会很方便。同时需要注意在dfs时保持入栈和退栈的协调。

class Solution:
    def fact(self,n):
        ans = 1
        for i in range(1,n+1):
            ans *= i 
        return ans

    def get(self, balls):
        all_balls = sum(balls)
        ans = self.fact(all_balls)
        for ball in balls:
            if ball:
                ans /= self.fact(ball)
        return ans

    def dfs(self, u, balls, right, left, rs, ls,allnum):
        # u 表示目前枚举到第几类球
        ## ball 总的球
        ## right,left 左侧的盒子,右侧盒子
        ## rs, ls 左右盒子已经放的球的数量
        ## allnum 总的球数量
        if rs*2>allnum or ls*2>allnum:
            return 0
        # 首先写出baseline,计算两边多少个不同的种类
        if len(balls) == u:
            l = 0
            r = 0
            for x in left:
                if x:
                    l += 1
            for x in right:
                if x:
                    r += 1
            if r == l:
                return self.get(right)*self.get(left)
            else:
                return 0
        # 递归计算
        res = 0
        for i in range(balls[u]+1):
            right[u] = i
            left[u] = balls[u]-i
            res += self.dfs(u+1, balls, right, left, rs+i, ls+balls[u]-i, allnum)
        return res


    def getProbability(self, balls: List[int]) -> float:
        n = len(balls)
        right = [0]*n
        left = [0]*n
        return self.dfs(0,balls,right, left, 0, 0, sum(balls))/self.get(balls)

你可能感兴趣的:(周赛总结)