Open In App

Count ways of selecting X red balls and Y blue balls

Last Updated : 29 Mar, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given integers A, B, C, and D, There are two boxes First Box has A red balls and B blue balls and the second box has C red balls and D blue balls, the task is to count ways to select 3 red balls and 3 blue balls so that there are 3 balls drawn from the first box and 3 balls drawn from the second box. (Print the answer modulo 109 + 7).

Examples:

Input: A = 4, B =3, C = 3, D = 4
Output: 485

Input: A = 3, B = 3, C = 3, D = 3
Output: 164

Naive approach: The basic way to solve the problem is as follows:

The basic way to solve this problem is to generate all possible combinations by using a recursive approach.

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

Efficient Approach:  The above approach can be optimized based on the following idea:

The problem can be solved with combinatorics:

Case 1: 2 red balls and 1 blue ball from box 1 and 1 red ball and 2 blue balls from box 2.

  • Total ways of case1 = AC2 * BC1 * CC1 * DC2 

Case 2: 3 red balls from box 1 and 3 blue balls from box 2.

  • Total ways of case2 = AC3 * DC3

Case 3: 3 blue balls from box1 and 3 red balls from box 2

  • Total ways of case3 = BC3 * CC3

Case 4: 1 red ball and 2 blue balls from box 1 and  2 red balls and 1 blue ball from box 2.

  • Total ways of case4 = AC1 * BC2 * CC2 * DC1 

Total ways = Total ways of case1 + Total ways of case2 + Total ways of case3 + Total ways of case 3 + Total ways of case4

instead of dividing factorials we multiply their modular multiplicative inverses.

Follow the steps below to solve the problem:

  • Initializing fact[] array and Precomputing all factorials from 1 to 100000.
  • initializing ANS variable.
  • Calculating the answer by using the above formula.
  • Print the answer.

Below is the implementation of the above approach:

C++




// C++ code to implement the approach
#include <bits/stdc++.h>
using namespace std;
 
// to avoid integer overflow
#define int long long
 
const int MOD = 1e9 + 7;
 
// To find GCD of a and b
int gcd(int a, int b);
 
// To compute x raised to power y under
// modulo M
int power(int x, unsigned int y, unsigned int M);
 
// Function to find modular inverse of
// under modulo M
// Assumption: M is prime
int modInverse(int A, int M)
{
    int g = gcd(A, M);
    return power(A, M - 2, M);
}
 
// To compute x^y under modulo m
int power(int x, unsigned int y, unsigned int M)
{
    if (y == 0)
        return 1;
 
    int p = power(x, y / 2, M) % M;
    p = (p * p) % M;
 
    return (y % 2 == 0) ? p : (x * p) % M;
}
 
// Function to return gcd of a and b
int gcd(int a, int b)
{
    if (a == 0)
        return b;
    return gcd(b % a, a);
}
 
// Function to Count number of ways
// of taking 3 red balls and 3 blue
// balls so that 3 balls are from box1
// and 3 balls are from box 2
int countWays(int A, int B, int C, int D)
{
 
    // Precomputation array storing
    // factorials MOD 1e9 + 7
    int fact[100001];
 
    // Initialize the base elements
    fact[1] = 1, fact[0] = 1;
 
    // Filling factorial table
    for (int i = 2; i <= 100000; i++) {
        fact[i] = (fact[i - 1] * i) % MOD;
    }
 
    // case 1 multiplying A!/(A-2)!
    int ans1
        = (fact[A] * modInverse(fact[A - 2], MOD)) % MOD;
 
    // case 1 multiplying B!/(B-1)!
    ans1 = (ans1 * fact[B] * modInverse(fact[B - 1], MOD))
           % MOD;
 
    // case 1 taking into account C!/(C-1)!
    ans1 = (ans1 * fact[C] * modInverse(fact[C - 1], MOD))
           % MOD;
 
    // case 1 taking into account D!/(D-1)!
    ans1 = (ans1 * fact[D] * modInverse(fact[D - 2], MOD))
           % MOD;
 
    // case 1 taking into account / 4
    ans1 = (ans1 * modInverse(4, MOD)) % MOD;
 
    // case 2 multiplying A!/(A-3)!
    int ans2
        = (fact[A] * modInverse(fact[A - 3], MOD)) % MOD;
 
    // case 2 multiplying D!/(D-3)!
    ans2 = (ans2 * fact[D] * modInverse(fact[D - 3], MOD))
           % MOD;
 
    // case 2 taking into account / 36
    ans2 = (ans2 * modInverse(36, MOD)) % MOD;
 
    // case 3 multiplying B!/(B-3)!
    int ans3
        = (fact[B] * modInverse(fact[B - 3], MOD)) % MOD;
 
    // case 3 multiplying C!/(C-3)!
    ans3 = (ans3 * fact[C] * modInverse(fact[C - 3], MOD))
           % MOD;
 
    // case 3 taking into account / 36
    ans3 = (ans3 * modInverse(36, MOD)) % MOD;
 
    // case 4 multiplying A!/(A-1)!
    int ans4
        = (fact[A] * modInverse(fact[A - 1], MOD)) % MOD;
 
    // case 4 multiplying B!/(B-2)!
    ans4 = (ans4 * fact[B] * modInverse(fact[B - 2], MOD))
           % MOD;
 
    // case 4 taking into account C!/(C-2)!
    ans4 = (ans4 * fact[C] * modInverse(fact[C - 2], MOD))
           % MOD;
 
    // case 4 taking into account D!/(D-1)!
    ans4 = (ans4 * fact[D] * modInverse(fact[D - 1], MOD))
           % MOD;
 
    // case 4 taking into accont / 4
    ans4 = (ans4 * modInverse(4, MOD)) % MOD;
 
    // answer
    int ans = (ans1 + ans2 + ans3 + ans4) % MOD;
 
    // Returning the answer
    return ans;
}
 
// Driver Code
int32_t main()
{
 
    // Input 1
    int A = 4, B = 3, C = 3, D = 4;
 
    // Function Call
    cout << countWays(A, B, C, D) << endl;
 
    // Input 2
    int A1 = 3, B1 = 3, C1 = 3, D1 = 3;
 
    // Function Call
    cout << countWays(A1, B1, C1, D1) << endl;
    return 0;
}


Java




// Java code for the above approach
import java.io.*;
class GFG {
 
  static final int MOD = (int)1e9 + 7;
 
  // To find GCD of a and b
  static int gcd(int a, int b)
  {
    if (a == 0)
      return b;
    return gcd(b % a, a);
  }
 
  // To compute x raised to power y under modulo M
  static int power(int x, int y, int M)
  {
    if (y == 0)
      return 1;
 
    int p = power(x, y / 2, M) % M;
    p = (int)((long)p * p % M);
 
    return (y % 2 == 0) ? p : (int)((long)x * p % M);
  }
 
  // Function to find modular inverse of A under modulo M
  // Assumption: M is prime
  static int modInverse(int A, int M)
  {
    int g = gcd(A, M);
    return power(A, M - 2, M);
  }
 
  // Function to Count number of ways
  // of taking 3 red balls and 3 blue
  // balls so that 3 balls are from box1
  // and 3 balls are from box 2
  static int countWays(int A, int B, int C, int D)
  {
 
    // Precomputation array storing factorials MOD 1e9 +
    // 7
    int[] fact = new int[100001];
 
    // Initialize the base elements
    fact[1] = 1;
    fact[0] = 1;
 
    // Fill factorial table
    for (int i = 2; i <= 100000; i++) {
      fact[i] = (int)((long)fact[i - 1] * i % MOD);
    }
 
    // case 1 multiplying A!/(A-2)!
    int ans1
      = (int)((long)fact[A]
              * modInverse(fact[A - 2], MOD) % MOD);
 
    // case 1 multiplying B!/(B-1)!
    ans1 = (int)((long)ans1 * fact[B] % MOD
                 * modInverse(fact[B - 1], MOD) % MOD);
 
    // case 1 taking into account C!/(C-1)!
    ans1 = (int)((long)ans1 * fact[C] % MOD
                 * modInverse(fact[C - 1], MOD) % MOD);
 
    // case 1 taking into account D!/(D-1)!
    ans1 = (int)((long)ans1 * fact[D] % MOD
                 * modInverse(fact[D - 2], MOD) % MOD);
 
    // case 1 taking into account / 4
    ans1 = (int)((long)ans1 * modInverse(4, MOD) % MOD);
 
    // case 2 multiplying A!/(A-3)!
    int ans2
      = (int)((long)fact[A]
              * modInverse(fact[A - 3], MOD) % MOD);
 
    // case 2 multiplying D!/(D-3)!
    ans2 = (int)((long)ans2 * fact[D] % MOD
                 * modInverse(fact[D - 3], MOD) % MOD);
 
    // case 2 taking into account / 36
    ans2
      = (int)((long)ans2 * modInverse(36, MOD) % MOD);
 
    // case 3 multiplying B!/(B-3)!
    int ans3
      = (int)((long)fact[B]
              * modInverse(fact[B - 3], MOD) % MOD);
 
    // case 3 multiplying C!/(C-3)!
    ans3 = (int)((long)ans3 * fact[C] % MOD
                 * modInverse(fact[C - 3], MOD) % MOD);
 
    // case 3 taking into account / 36
    ans3
      = (int)((long)ans3 * modInverse(36, MOD) % MOD);
 
    // case 4 multiplying A!/(A-1)!
    int ans4
      = (int)((long)fact[A]
              * modInverse(fact[A - 1], MOD) % MOD);
 
    // case 4 multiplying B!/(B-2)!
    ans4 = (int)((long)ans4 * fact[B] % MOD
                 * modInverse(fact[B - 2], MOD) % MOD);
 
    // case 4 taking into account C!/(C-2)!
    ans4 = (int)((long)ans4 * fact[C] % MOD
                 * modInverse(fact[C - 2], MOD) % MOD);
 
    // case 4 taking into account D!/(D-2)!
    ans4 = (int)((long)ans4 * fact[D] % MOD
                 * modInverse(fact[D - 1], MOD) % MOD);
 
    // case 4 taking into account / 12
    ans4 = (int)((long)ans4 * modInverse(4, MOD) % MOD);
 
    return (ans1 + ans2 + ans3 + ans4) % MOD;
  }
 
  public static void main(String[] args)
  {
     
    // Input 1
    int A = 4, B = 3, C = 3, D = 4;
 
    // Function Call
    System.out.println(countWays(A, B, C, D));
 
    // Input 2
    int A1 = 3, B1 = 3, C1 = 3, D1 = 3;
 
    // Function Call
    System.out.println(countWays(A1, B1, C1, D1));
  }
}
 
// This code is contributed by lokesh.


Python3




# Python code for the above approach
import math
 
MOD = int(1e9 + 7)
 
# To find GCD of a and b
def gcd(a: int, b: int) -> int:
    if a == 0:
        return b
    return gcd(b % a, a)
 
# To compute x raised to power y under
# modulo M
def power(x: int, y: int, M: int) -> int:
    if y == 0:
        return 1
    p = power(x, y // 2, M) % M
    p = (p * p) % M
    return (p if y % 2 == 0 else (x * p) % M)
 
# Function to find modular inverse of
# under modulo M
# Assumption: M is prime
def modInverse(A: int, M: int) -> int:
    g = gcd(A, M)
    return power(A, M - 2, M)
 
# Function to Count number of ways
# of taking 3 red balls and 3 blue
# balls so that 3 balls are from box1
# and 3 balls are from box 2
def countWays(A: int, B: int, C: int, D: int) -> int:
    # Precomputation array storing
    # factorials MOD 1e9 + 7
    fact = [1 for i in range(100001)]
    # Filling factorial table
    for i in range(2, 100001):
        fact[i] = (fact[i - 1] * i) % MOD
 
    # case 1 multiplying A!/(A-2)!
    ans1 = (fact[A] * modInverse(fact[A - 2], MOD)) % MOD
    # case 1 multiplying B!/(B-1)!
    ans1 = (ans1 * fact[B] * modInverse(fact[B - 1], MOD)) % MOD
    # case 1 taking into account C!/(C-1)!
    ans1 = (ans1 * fact[C] * modInverse(fact[C - 1], MOD)) % MOD
    # case 1 taking into account D!/(D-1)!
    ans1 = (ans1 * fact[D] * modInverse(fact[D - 2], MOD)) % MOD
 
    # case 1 taking into account / 4
    ans1 = (ans1 * modInverse(4, MOD)) % MOD
 
    # case 2 multiplying A!/(A-3)!
    ans2 = (fact[A] * modInverse(fact[A - 3], MOD)) % MOD
    # case 2 multiplying D!/(D-3)!
    ans2 = (ans2 * fact[D] * modInverse(fact[D - 3], MOD)) % MOD
    # case 2 taking into account / 36
    ans2 = (ans2 * modInverse(36, MOD)) % MOD
 
    # case 3 multiplying B!/(B-3)!
    ans3 = (fact[B] * modInverse(fact[B - 3], MOD)) % MOD
    # case 3 multiplying C!/(C-3)!
    ans3 = (ans3 * fact[C] * modInverse(fact[C - 3], MOD)) % MOD
    # case 3 taking into account / 36
    ans3 = (ans3 * modInverse(36, MOD)) % MOD
 
    # case 4 multiplying A!/(A-1)!
    ans4 = (fact[A] * modInverse(fact[A - 1], MOD)) % MOD
    # case 4 multiplying B!/(B-2)!
    ans4 = (ans4 * fact[B] * modInverse(fact[B - 2], MOD)) % MOD
    # case 4 taking into account C!/(C-2)!
    ans4 = (ans4 * fact[C] * modInverse(fact[C - 2], MOD)) % MOD
    # case 4 taking into account D!/(D-2)!
    ans4 = (ans4 * fact[D] * modInverse(fact[D - 1], MOD)) % MOD
    # case 4 taking into account / 12
    ans4 = (ans4 * modInverse(4, MOD)) % MOD
 
    # Return the final answer
    return (ans1 + ans2 + ans3 + ans4) % MOD
   
# Driver code
if __name__ == '__main__':
    A = 4 # Number of red balls in box 1
    B = 3 # Number of blue balls in box 1
    C = 3 # Number of red balls in box 2
    D = 4 # Number of blue balls in box 2
    # Function call to find number of ways
    print(int(countWays(A, B, C, D)))
    A = 3# Number of red balls in box 1
    B = 3 # Number of blue balls in box 1
    C = 3 # Number of red balls in box 2
    D = 3 # Number of blue balls in box 2
    # Function call to find number of ways
    print(int(countWays(A, B, C, D)))
     
# This code is contributed by Potta Lokesh


C#




// C# code to implement the approach
using System;
using System.Collections.Generic;
 
class GFG {
 
  const long MOD = 1000000007;
 
  // Function to return gcd of a and b
  static long gcd(long a, long b)
  {
    if (a == 0)
      return b;
    return gcd(b % a, a);
  }
 
  // To compute x^y under modulo m
  static long power(long x,  long y,  long M)
  {
    if (y == 0)
      return 1;
 
    long p = power(x, y / 2, M) % M;
    p = (p * p) % M;
 
    return (y % 2 == 0) ? p : (x * p) % M;
  }
 
  // Function to find modular inverse of
  // under modulo M
  // Assumption: M is prime
  static long modInverse(long A, long M)
  {
    long g = gcd(A, M);
    return power(A, M - 2, M);
  }
 
  // Function to Count number of ways
  // of taking 3 red balls and 3 blue
  // balls so that 3 balls are from box1
  // and 3 balls are from box 2
  static long countWays(long A, long B, long C, long D)
  {
 
    // Precomputation array storing
    // factorials MOD 1e9 + 7
    long[] fact=new long[100001];
 
    // Initialize the base elements
    fact[1] = 1;
    fact[0] = 1;
 
    // Filling factorial table
    for (long i = 2; i <= 100000; i++) {
      fact[i] = (fact[i - 1] * i) % MOD;
    }
 
    // case 1 multiplying A!/(A-2)!
    long ans1
      = (fact[A] * modInverse(fact[A - 2], MOD)) % MOD;
 
    // case 1 multiplying B!/(B-1)!
    ans1 = (ans1 * fact[B] * modInverse(fact[B - 1], MOD))
      % MOD;
 
    // case 1 taking longo account C!/(C-1)!
    ans1 = (ans1 * fact[C] * modInverse(fact[C - 1], MOD))
      % MOD;
 
    // case 1 taking longo account D!/(D-1)!
    ans1 = (ans1 * fact[D] * modInverse(fact[D - 2], MOD))
      % MOD;
 
    // case 1 taking longo account / 4
    ans1 = (ans1 * modInverse(4, MOD)) % MOD;
 
    // case 2 multiplying A!/(A-3)!
    long ans2
      = (fact[A] * modInverse(fact[A - 3], MOD)) % MOD;
 
    // case 2 multiplying D!/(D-3)!
    ans2 = (ans2 * fact[D] * modInverse(fact[D - 3], MOD))
      % MOD;
 
    // case 2 taking longo account / 36
    ans2 = (ans2 * modInverse(36, MOD)) % MOD;
 
    // case 3 multiplying B!/(B-3)!
    long ans3
      = (fact[B] * modInverse(fact[B - 3], MOD)) % MOD;
 
    // case 3 multiplying C!/(C-3)!
    ans3 = (ans3 * fact[C] * modInverse(fact[C - 3], MOD))
      % MOD;
 
    // case 3 taking longo account / 36
    ans3 = (ans3 * modInverse(36, MOD)) % MOD;
 
    // case 4 multiplying A!/(A-1)!
    long ans4
      = (fact[A] * modInverse(fact[A - 1], MOD)) % MOD;
 
    // case 4 multiplying B!/(B-2)!
    ans4 = (ans4 * fact[B] * modInverse(fact[B - 2], MOD))
      % MOD;
 
    // case 4 taking longo account C!/(C-2)!
    ans4 = (ans4 * fact[C] * modInverse(fact[C - 2], MOD))
      % MOD;
 
    // case 4 taking longo account D!/(D-1)!
    ans4 = (ans4 * fact[D] * modInverse(fact[D - 1], MOD))
      % MOD;
 
    // case 4 taking longo accont / 4
    ans4 = (ans4 * modInverse(4, MOD)) % MOD;
 
    // answer
    long ans = (ans1 + ans2 + ans3 + ans4) % MOD;
 
    // Returning the answer
    return ans;
  }
 
  // Driver Code
  public static void Main()
  {
 
    // Input 1
    long A = 4, B = 3, C = 3, D = 4;
 
    // Function Call
    Console.Write(countWays(A, B, C, D)+"\n");
 
    // Input 2
    long A1 = 3, B1 = 3, C1 = 3, D1 = 3;
 
    // Function Call
    Console.Write(countWays(A1, B1, C1, D1)+"\n");
  }
}
 
// This code is contributed by agrawalpoojaa976.


Javascript




// Javascript code for the above approach
const MOD = BigInt(1e9 + 7);
 
// To find GCD of a and b
function gcd(a, b) {
  if (a == 0n) {
    return b;
  }
  return gcd(b % a, a);
}
// To compute x raised to power y under
// modulo M
function power(x, y, M) {
  if (y == 0n) {
    return 1n;
  }
  let p = power(x, y / 2n, M) % M;
  p = (p * p) % M;
  return (y % 2n == 0n ? p : (x * p) % M);
}
 
// Function to find modular inverse of
// under modulo M
// Assumption: M is prime
function modInverse(A, M) {
  const g = gcd(A, M);
  return power(A, M - 2n, M);
}
 
// Function to Count number of ways
// of taking 3 red balls and 3 blue
// balls so that 3 balls are from box1
// and 3 balls are from box 2
function countWays(A, B, C, D) {
    // Precomputation array storing
    // factorials MOD 1e9 + 7
  const fact = [BigInt(1)];
  // Filling factorial table
  for (let i = 1n; i <= 100000n; i++) {
    fact.push((fact[i - 1n] * i) % MOD);
  }
  // case 1 multiplying A!/(A-2)!
  let ans1 = (fact[A] * modInverse(fact[A - 2n], MOD)) % MOD;
   
  // case 1 multiplying B!/(B-1)!
  ans1 = (ans1 * fact[B] * modInverse(fact[B - 1n], MOD)) % MOD;
   
  // case 1 taking into account C!/(C-1)!
  ans1 = (ans1 * fact[C] * modInverse(fact[C - 1n], MOD)) % MOD;
   
   // case 1 taking into account D!/(D-1)!
  ans1 = (ans1 * fact[D] * modInverse(fact[D - 2n], MOD)) % MOD;
     
  // case 1 taking into account / 4
  ans1 = (ans1 * modInverse(4n, MOD)) % MOD;
 
  // case 2 multiplying A!/(A-3)!
  let ans2 = (fact[A] * modInverse(fact[A - 3n], MOD)) % MOD;
   
   // case 2 multiplying D!/(D-3)!
  ans2 = (ans2 * fact[D] * modInverse(fact[D - 3n], MOD)) % MOD;
   
  // case 2 taking into account / 36
  ans2 = (ans2 * modInverse(36n, MOD)) % MOD;
 
  // case 3 multiplying B!/(B-3)!
  let ans3 = (fact[B] * modInverse(fact[B - 3n], MOD)) % MOD;
   
  // case 3 multiplying C!/(C-3)!
  ans3 = (ans3 * fact[C] * modInverse(fact[C - 3n], MOD)) % MOD;
   
  // case 3 taking into account / 36
  ans3 = (ans3 * modInverse(36n, MOD)) % MOD;
     
  // case 4 multiplying A!/(A-1)!
  let ans4 = (fact[A] * modInverse(fact[A - 1n], MOD)) % MOD;
   
  // case 4 multiplying B!/(B-2)!
  ans4 = (ans4 * fact[B] * modInverse(fact[B - 2n], MOD)) % MOD;
   
  // case 4 taking into account C!/(C-2)!
  ans4 = (ans4 * fact[C] * modInverse(fact[C - 2n], MOD)) % MOD;
   
  // case 4 taking into account D!/(D-2)!
  ans4 = (ans4 * fact[D] * modInverse(fact[D - 1n], MOD)) % MOD;
   
  // case 4 taking into account / 12
  ans4 = (ans4 * modInverse(4n, MOD)) % MOD;
 
  // Return the final answer
  return Number((ans1 + ans2 + ans3 + ans4) % MOD);
}
 
// Driver Code
console.log(countWays(4n, 3n, 3n, 4n));
console.log(countWays(3n, 3n, 3n, 3n));
 
// This code is contributed by sdeadityasharma


Output

485
164

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

Related Articles:



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads