Open In App

Probability of distributing given balls into two halves having equal count of distinct colors

Last Updated : 22 Jun, 2021
Improve
Improve
Like Article
Like
Save
Share
Report

Given an array arr[] of size N, representing the number of balls of each of N distinct colors, the task is to find the probability of distributing all the balls into two boxes, such that both the boxes contain an equal number of distinct colored balls.

Examples:

Input: arr[] = {1, 1}, N = 2
Output: 1.00000
Explanation: Two possible ways to distribute them are as follows: 
Put the ball of 0th color type in the 1st box and the ball of 1st color type into the 2nd box. 
Put the color of 1st type in the 1st box and the color of 0th type in the 2nd box. 
Therefore, the probability is equal to (2 / 2) = 1.00000

Input: arr[] = {2, 1, 1}, N = 3
Output: 0.66667

Approach: The idea is to use combinatorics and backtracking to solve the problem. The given problem can be solved based on the following observations:

  • Suppose X is the total number of ways to distribute K balls into two equal halves.
  • It can be observed that X is the same as choosing K/2 balls from the K balls, which is equal to KC(K/2).
  • The total number of ways of distributing the balls such that both the boxes contain the same number of balls and same number of total distinct colors, say Y, can be calculated using Backtracking, by choosing j balls from the arr[i] and putting it in a box for every 0 ? i < N and j ? arr[i], and place the remaining balls in the other box.
  • Therefore, the required probability is Y/X.

Follow the steps below to solve the problem:

  • Calculate the sum of all elements present in the array arr[] in a variable, say K.
  • Print 0 if K is an odd number.
  • Calculate the number of ways of selecting K/2 balls and store it in a variable, say X.
  • Define a recursive function, say validPermutations(pos, usedBalls, box1, box2), and perform the following steps:
    • Define the base case: If usedBalls is equal to K/2, then return 1 if box1 = box2. Otherwise, return 0.
    • If pos ? N, then return 0.
    • Now, initialize a variable, say res, to store the number of ways of distributing the remaining balls.
    • Iterate over the range [0, arr[pos]]:
      • Assign box1, and box2 to variables, say newbox1 and newbox2 respectively.
      • Increment newbox1 by one if j > 0 and newbox2, if j < arr[pos].
      • Now, update res as res = res + arr[pos]Cj * validPermutations(pos+1, usedBalls+j, newbox1, newbox2).
    • Return the value of res.
  • Call the function validPermutations(0, 0, 0, 0) and store it in a variable, say Y.
  • Finally, print the result obtained as Y/X.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Stores the count of
// distinct colors in box1
static int box1 = 0;
 
// Stores the count of
// distinct colors in box2
static int box2 = 0;
 
static int fact[11];
 
// Function to calculate NcR
long comb(int n, int r)
{
    long res = fact[n] / fact[r];
    res /= fact[n - r];
    return res;
}
 
// Function to calculate factorial of N
void factorial(int N)
{
     
    // Base Case
    fact[0] = 1;
 
    // Iterate over the range [1, N]
    for(int i = 1; i <= N; i++)
        fact[i] = fact[i - 1] * i;
}
 
// Function to calculate total number
// of possible distributions which
// satisfies the given conditions
long validPermutations(int n, int balls[],
                       int usedBalls,
                       int i, int M)
{
     
    // If used balls is equal to K/2
    if (usedBalls == n)
    {
         
        // If box1 is equal to box2
        return box1 == box2 ? 1 : 0;
    }
 
    // Base condition
    if (i >= M)
        return 0;
 
    // Stores the number of ways of
    // distributing remaining balls without
    // including the current balls in box1
    long res = validPermutations(n, balls,
                                 usedBalls,
                                 i + 1, M);
 
    // Increment box1 by one
    box1++;
 
    // Iterate over the range [1, balls[i]]
    for(int j = 1; j <= balls[i]; j++)
    {
         
        // If all the balls goes to box1,
        // then decrease box2 by one
        if (j == balls[i])
 
            box2--;
 
        // Total number of ways of
        // selecting j balls
        long combinations = comb(balls[i], j);
 
        // Increment res by total number of valid
        // ways of distributing the remaining balls
        res += combinations * validPermutations(n, balls,
                                                usedBalls + j,
                                                i + 1, M);
    }
 
    // Decrement box1 by one
    box1--;
 
    // Increment box2 by 1
    box2++;
 
    return res;
}
 
// Function to calculate the required probability
double getProbability(int balls[], int M)
{
     
    // Calculate factorial from [1, 10]
    factorial(10);
 
    // Assign all distinct balls to second box
    box2 = M;
 
    // Total number of balls
    int K = 0;
 
    // Calculate total number of balls
    for(int i = 0; i < M; i++)
        K += balls[i];
 
    // If K is an odd number
    if (K % 2 == 1)
        return 0;
 
    // Total ways of distributing the balls
    // in two equal halves
    long all = comb(K, K / 2);
 
    // Required number of ways
    long validPermutation = validPermutations(K / 2, balls,
                                              0, 0, M);
 
    // Return the required probability
    return (double)validPermutation / all;
}
 
// Driver Code
int main()
{
    int arr[] = { 2, 1, 1 };
    int N = 4;
    int M = sizeof(arr) / sizeof(arr[0]);
 
    // Print the result
    cout << (getProbability(arr, M));
     
    return 0;
}
 
// This code is contributed by ukasp


Java




// Java program for the above approach
 
import java.io.*;
import java.util.*;
 
class GFG {
 
    // Stores the count of
    // distinct colors in box1
    static int box1 = 0;
 
    // Stores the count of
    // distinct colors in box2
    static int box2 = 0;
 
    static int[] fact = new int[11];
 
    // Function to calculate the required probability
    public static double getProbability(int[] balls)
    {
 
        // Calculate factorial from [1, 10]
        factorial(10);
 
        // Assign all distinct balls to second box
        box2 = balls.length;
 
        // Total number of balls
        int K = 0;
 
        // Calculate total number of balls
        for (int i = 0; i < balls.length; i++)
            K += balls[i];
 
        // If K is an odd number
        if (K % 2 == 1)
            return 0;
 
        // Total ways of distributing the balls
        // in two equal halves
        long all = comb(K, K / 2);
 
        // Required number of ways
        long validPermutations = validPermutations(K / 2, balls, 0, 0);
 
        // Return the required probability
        return (double)validPermutations / all;
    }
 
    // Function to calculate total number
    // of possible distributions which
    // satisfies the given conditions
    static long validPermutations(int n, int[] balls,
                          int usedBalls, int i)
    {
 
        // If used balls is equal to K/2
        if (usedBalls == n) {
 
            // If box1 is equal to box2
            return box1 == box2 ? 1 : 0;
        }
 
        // Base condition
        if (i >= balls.length)
            return 0;
 
        // Stores the number of ways of
        // distributing remaining balls without
        // including the current balls in box1
        long res = validPermutations(n, balls, usedBalls, i + 1);
 
        // Increment box1 by one
        box1++;
 
        // Iterate over the range [1, balls[i]]
        for (int j = 1; j <= balls[i]; j++) {
 
            // If all the balls goes to box1,
            // then decrease box2 by one
            if (j == balls[i])
                box2--;
 
            // Total number of ways of
            // selecting j balls
            long combinations = comb(balls[i], j);
 
            // Increment res by total number of valid
            // ways of distributing the remaining balls
            res += combinations * validPermutations(n, balls,
                                            usedBalls + j, i + 1);
        }
 
        // Decrement box1 by one
        box1--;
 
        // Increment box2 by 1
        box2++;
 
        return res;
    }
 
    // Function to calculate factorial of N
    static void factorial(int N)
    {
 
        // Base Case
        fact[0] = 1;
 
        // Iterate over the range [1, N]
        for (int i = 1; i <= N; i++)
            fact[i] = fact[i - 1] * i;
    }
 
    // Function to calculate NcR
    static long comb(int n, int r)
    {
 
        long res = fact[n] / fact[r];
        res /= fact[n - r];
        return res;
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        int[] arr = { 2, 1, 1 };
        int N = 4;
 
        // Print the result
        System.out.println(getProbability(arr));
    }
}


Python3




# Python3 program for the above approach
 
# Stores the count of
# distinct colors in box1
box1 = 0
 
# Stores the count of
# distinct colors in box2
box2 = 0
 
fact = [0 for i in range(11)]
 
# Function to calculate the required probability
def getProbability(balls):
     
    global box1, box2, fact
     
    # Calculate factorial from [1, 10]
    factorial(10)
     
    # Assign all distinct balls to second box
    box2 = len(balls)
     
    # Total number of balls
    K = 0
     
    # Calculate total number of balls
    for i in range(len(balls)):
        K += balls[i]
     
    # If K is an odd number   
    if (K % 2 == 1):
        return 0
     
    # Total ways of distributing the balls
    # in two equal halves
    all = comb(K, K // 2)
     
    # Required number of ways
    validPermutation = validPermutations(
        K // 2, balls, 0, 0)
     
    # Return the required probability
    return validPermutation / all
 
# Function to calculate total number
# of possible distributions which
# satisfies the given conditions
def validPermutations(n, balls, usedBalls, i):
     
    global box1, box2, fact
     
    # If used balls is equal to K/2
    if (usedBalls == n):
         
        # If box1 is equal to box2
        if (box1 == box2):
            return 1
        else:
            return 0
             
    # Base condition
    if (i >= len(balls)):
        return 0
     
    # Stores the number of ways of
    # distributing remaining balls without
    # including the current balls in box1
    res = validPermutations(n, balls,
                            usedBalls, i + 1)
     
    # Increment box1 by one
    box1 += 1
     
    # Iterate over the range [1, balls[i]]
    for j in range(1, balls[i] + 1):
         
        # If all the balls goes to box1,
        # then decrease box2 by one
        if (j == balls[i]):
            box2 -= 1
         
        # Total number of ways of
        # selecting j balls
        combinations = comb(balls[i], j)
         
        # Increment res by total number of valid
        # ways of distributing the remaining balls
        res += combinations * validPermutations(n, balls,
                                                usedBalls + j,
                                                i + 1)
     
    # Decrement box1 by one
    box1 -= 1
     
    # Increment box2 by 1
    box2 += 1
     
    return res
 
# Function to calculate factorial of N
def factorial(N):
     
    global box1, box2, fact
     
    # Base Case
    fact[0] = 1
     
    # Iterate over the range [1, N]
    for i in range(1, N + 1):
        fact[i] = fact[i - 1] * i
     
# Function to calculate NcR   
def comb(n, r):
     
    global box1, box2, fact
    res = fact[n] // fact[r]
    res //= fact[n - r]
    return res
     
# Driver Code   
arr = [ 2, 1, 1 ]
N = 4
 
print(getProbability(arr))
 
# This code is contributed by avanitrachhadiya2155


C#




// C# program for the above approach
using System;
public class GFG
{
 
    // Stores the count of
    // distinct colors in box1
    static int box1 = 0;
 
    // Stores the count of
    // distinct colors in box2
    static int box2 = 0;
    static int[] fact = new int[11];
 
    // Function to calculate the required probability
    public static double getProbability(int[] balls)
    {
 
        // Calculate factorial from [1, 10]
        factorial(10);
 
        // Assign all distinct balls to second box
        box2 = balls.Length;
 
        // Total number of balls
        int K = 0;
 
        // Calculate total number of balls
        for (int i = 0; i < balls.Length; i++)
            K += balls[i];
 
        // If K is an odd number
        if (K % 2 == 1)
            return 0;
 
        // Total ways of distributing the balls
        // in two equal halves
        long all = comb(K, K / 2);
 
        // Required number of ways
        long validPermutationss = validPermutations((K / 2), balls, 0, 0);
 
        // Return the required probability
        return (double)validPermutationss / all;
    }
 
    // Function to calculate total number
    // of possible distributions which
    // satisfies the given conditions
    static long validPermutations(int n, int[] balls,
                          int usedBalls, int i)
    {
 
        // If used balls is equal to K/2
        if (usedBalls == n)
        {
 
            // If box1 is equal to box2
            return box1 == box2 ? 1 : 0;
        }
 
        // Base condition
        if (i >= balls.Length)
            return 0;
 
        // Stores the number of ways of
        // distributing remaining balls without
        // including the current balls in box1
        long res = validPermutations(n, balls, usedBalls, i + 1);
 
        // Increment box1 by one
        box1++;
 
        // Iterate over the range [1, balls[i]]
        for (int j = 1; j <= balls[i]; j++)
        {
 
            // If all the balls goes to box1,
            // then decrease box2 by one
            if (j == balls[i])
                box2--;
 
            // Total number of ways of
            // selecting j balls
            long combinations = comb(balls[i], j);
 
            // Increment res by total number of valid
            // ways of distributing the remaining balls
            res += combinations * validPermutations(n, balls,
                                            usedBalls + j, i + 1);
        }
 
        // Decrement box1 by one
        box1--;
 
        // Increment box2 by 1
        box2++;
 
        return res;
    }
 
    // Function to calculate factorial of N
    static void factorial(int N)
    {
 
        // Base Case
        fact[0] = 1;
 
        // Iterate over the range [1, N]
        for (int i = 1; i <= N; i++)
            fact[i] = fact[i - 1] * i;
    }
 
    // Function to calculate NcR
    static long comb(int n, int r)
    {
 
        long res = fact[n] / fact[r];
        res /= fact[n - r];
        return res;
    }
 
    // Driver Code
    public static void Main(String[] args)
    {
        int[] arr = { 2, 1, 1 };
        int N = 4;
 
        // Print the result
        Console.WriteLine(getProbability(arr));
    }
}
 
// This code is contributed by 29AjayKumar


Javascript




<script>
 
// Javascript program for the above approach
 
// Stores the count of
// distinct colors in box1
var box1 = 0;
 
// Stores the count of
// distinct colors in box2
var box2 = 0;
 
var fact = Array(11);
 
// Function to calculate NcR
function comb(n, r)
{
    var res = fact[n] / fact[r];
    res /= fact[n - r];
    return res;
}
 
// Function to calculate factorial of N
function factorial(N)
{
     
    // Base Case
    fact[0] = 1;
 
    // Iterate over the range [1, N]
    for(var i = 1; i <= N; i++)
        fact[i] = fact[i - 1] * i;
}
 
// Function to calculate total number
// of possible distributions which
// satisfies the given conditions
function validPermutations(n, balls,usedBalls, i, M)
{
     
    // If used balls is equal to K/2
    if (usedBalls == n)
    {
         
        // If box1 is equal to box2
        return box1 == box2 ? 1 : 0;
    }
 
    // Base condition
    if (i >= M)
        return 0;
 
    // Stores the number of ways of
    // distributing remaining balls without
    // including the current balls in box1
    var res = validPermutations(n, balls,
                                 usedBalls,
                                 i + 1, M);
 
    // Increment box1 by one
    box1++;
 
    // Iterate over the range [1, balls[i]]
    for(var j = 1; j <= balls[i]; j++)
    {
         
        // If all the balls goes to box1,
        // then decrease box2 by one
        if (j == balls[i])
 
            box2--;
 
        // Total number of ways of
        // selecting j balls
        var combinations = comb(balls[i], j);
 
        // Increment res by total number of valid
        // ways of distributing the remaining balls
        res += combinations * validPermutations(n, balls,
                                                usedBalls + j,
                                                i + 1, M);
    }
 
    // Decrement box1 by one
    box1--;
 
    // Increment box2 by 1
    box2++;
 
    return res;
}
 
// Function to calculate the required probability
function getProbability(balls, M)
{
     
    // Calculate factorial from [1, 10]
    factorial(10);
 
    // Assign all distinct balls to second box
    box2 = M;
 
    // Total number of balls
    var K = 0;
 
    // Calculate total number of balls
    for(var i = 0; i < M; i++)
        K += balls[i];
 
    // If K is an odd number
    if (K % 2 == 1)
        return 0;
 
    // Total ways of distributing the balls
    // in two equal halves
    var all = comb(K, K / 2);
 
    // Required number of ways
    var validPermutation = validPermutations(K / 2, balls,
                                              0, 0, M);
 
    // Return the required probability
    return validPermutation / all;
}
 
// Driver Code
var arr = [2, 1, 1];
var N = 4;
var M = arr.length;
// Print the result
document.write(getProbability(arr, M));
 
</script>


Output: 

0.6666666666666666

 

Time Complexity: O(N!)
Auxiliary Space: O(1)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads