Skip to content

Latest commit

 

History

History

1467.Probability-of-a-Two-Boxes-Having-The-Same-Number-of-Distinct-Balls

1467.Probability-of-a-Two-Boxes-Having-The-Same-Number-of-Distinct-Balls

本题的第二个例子描述的并不好。我们将三个颜色的四个球标记为(1a, 1b, 2, 3)。分母应该是任意分成两等份的方案数,即C(4,2)=6,分子有四种合法方案:(1a,2)/(1b,3), (1a,3)/(1b,2), (1b,2)/(1a,3), (1b,3)/(1a,2). 答案就是4/6 = 0.67. 注意我们不关心同一组里球的具体顺序。

此题的方法比较暴力。我们枚举每种颜色的球的拆分方案,即考虑如何拆分为两部分。将所有的颜色都处理完了,我们来看这两组球的情况:如果两组球的总数不相等,则连做分母的资格都没有。如果两组球的总数相等,方案数可以加入分母。如果两组球的颜色数目相等,方案数另外可以加入分子。于是,这道题本质就是一个递归。

那么确定两组球的情况后,如何求对应的方案数呢?假设颜色i的球总数是xi,对于第一组而言分到了yi个球,那么总方案数就是product { C(xi, yi) } for all i. 其中C表示组合数。我们知道对于每种颜色,球的数目不超过8,也就是说组合数的上下标都不会超过8。我们通常的处理方案是把所有的组合数都算出来。

如何高效地求所有组合数呢?我们不会直接按照定义去求,因为那会涉及到阶乘和除法。我们会用到递推公式:

C(i,j) = C(i-1, j-1) + C(i-1, j)

可以这么理解。我们要在i个球里面取j个,我们有两种分支:前i-1个球里面取j-1个,第i个球必取。或者前i-1个球里面直接取j个。两种分支的方案总和就是C(i,j).这有一套模板代码可以套用:

        int C[10][10];
        for (int i = 0; i <= 8; ++i) {
            C[i][i] = C[i][0] = 1;            
            for (int j = 1; j < i; ++j) {
                C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
            }
        }   

本题的时间DFS的复杂度是6^8 = 1679616,可以接受,