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.00000Input: 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> |
0.6666666666666666
Time Complexity: O(N!)
Auxiliary Space: O(1)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!