Given non-negative integers X, Y, and Z for each M query. Given X amount of character ‘A’, Y amount of character ‘B’, and Z amount of character ‘C’. The task is to print for each query, the number of ways modulo 109 + 7 of arranging these characters in a row so that at least one character is separated from a character of the same type.
AABBCCC, BBBBBCCCCAAA, and ABBBCCCCC are some invalid answers since no characters are separated from characters of the same type.
Examples:
Input: Q[][3] = {{1, 1, 1}, {1, 2, 1}, {2, 2, 1}}, N = 3
Output: 0 6 24
Explanation: For query 1: X = 1, Y = 1, and Z = 1, with these characters it is not possible to arrange them in such a way that at least one character is separated from characters of the same type.
For query 2: X = 1, Y = 2, and Z = 1, with these there are 6 possible arrangements ABCB, BACB, BABC, CBAB, BCAB, and BCBA.
For query 3: X = 2, Y = 2 and Z = 1 with these there are 24 possible arrangements.Input: Q1[][3] = {{2, 3, 5}, {5, 6, 7}, {8, 9, 10}}, N = 3
Output: 2514 14702682 86086909
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.number
Time Complexity: O(N!)
Auxiliary Space: O(1)
Efficient Approach: The above approach can be optimized based on the following idea:
Combinatorics can be used along with binary exponentiation and modulo multiplicative inverse to solve this problem
- Precomputing factorials for each query.
- Total permutations = 0 characters separated + 1 character separated + 2 characters separated + 3 characters separated + …………………. = (X + Y + Z)! / (X! * Y! * Z!).
- It will suffice to exclude 0 characters separated permutations from Total permutations in order to find out permutations with at least 1 character separated.
- Total permutations with at least 1 character separated = Total permutations with no restriction – permutations with zero 0 characters separated.
- if we consider all same characters as one object there are 3! ways of permutating them.
- Total permutations with at least 1 character separated = (X + Y + Z)! / (X! * Y! * Z!) – 3! = (X + Y + Z)! / (X! * Y! * Z!) – 6
- For calculation instead of division by X! , Y! and Z!. Its better to multiplying answer by modulo multiplicative inverse of X!, Y! and Z! along with stepwise multiplication to avoid integer overflow.
Follow the steps below to solve the problem:
- Making factorial array fact[] for precomputation and filling the array with factorials of numbers from 1 to 100000.
- Traversing for each query 1 to M and printing the answer by the above formula.
Below is the implementation of the above approach:
C++
// C++ code to implement the approach #include <bits/stdc++.h> using namespace std; #define int long long const int MOD = 1e9 + 7; // 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 a // under modulo M // Assumption: M is prime int modInverse( int A, int M) { // If a and m are relatively prime, // then modulo inverse is // a^(m-2) mode 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 print Count ways given // characters arranged in row so that // at least on character is separated // from character of same type for each M // queries. void findWays( int Q[][3], int M) { // Precomputing factorial array int fact[100001]; // Factorial of 1 is 1 fact[1] = 1; // Finding factorial of all 1e5 numbers for ( int i = 2; i <= 1e5; i++) { fact[i] = (fact[i - 1] * i) % MOD; } // Traversing for each query for ( int i = 0; i < M; i++) { // X, Y and Z for i'th query int X = Q[i][0], Y = Q[i][1], Z = Q[i][2]; // Total permutation = // (X + Y + Z)! / X! int ans = (fact[X + Y + Z] * modInverse(fact[X], MOD)) % MOD; // Total permutation = // (X + Y + Z)! / (X! * Y!) ans = (ans * modInverse(fact[Y], MOD)) % MOD; // Total permutation = // (X + Y + Z)! (X! * Y! * Z!) ans = (ans * modInverse(fact[Z], MOD)) % MOD; // Printing answer cout << ans - 6 << " " ; } cout << endl; } // Driver Code int32_t main() { // Test Case 1 int Q[][3] = { { 1, 1, 1 }, { 1, 2, 1 }, { 2, 2, 1 } }, N = 3; // Function Call findWays(Q, N); // Test Case 2 int Q1[][3] = { { 2, 3, 5 }, { 5, 6, 7 }, { 8, 9, 10 } }, N1 = 3; // Function Call findWays(Q1, N1); return 0; } |
Java
// Java code to implement the approach import java.io.*; import java.util.*; class GFG { final static long MOD = ( long )1e9 + 7 ; // To compute x raised to power 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 a // under modulo M // Assumption: M is prime static long modInverse( long A, long M) { // If a and m are relatively prime, // then modulo inverse is // a^(m-2) mode m return power(A, M - 2 , M); } // Function to print Count ways given // characters arranged in row so that // at least on character is separated // from character of same type for each M // queries. static void findWays( int [][] Q, int M) { // Precomputing factorial array long [] fact = new long [ 100001 ]; // Factorial of 1 is 1 fact[ 1 ] = 1 ; // Finding factorial of all 1e5 numbers for ( int i = 2 ; i <= 1e5; i++) { fact[i] = (fact[i - 1 ] * i) % MOD; } // Traversing for each query for ( int i = 0 ; i < M; i++) { // X, Y and Z for i'th query int X = Q[i][ 0 ], Y = Q[i][ 1 ], Z = Q[i][ 2 ]; // Total permutation = // (X + Y + Z)! / X! long ans = (fact[X + Y + Z] * modInverse(fact[X], MOD)) % MOD; // Total permutation = // (X + Y + Z)! / (X! * Y!) ans = (ans * modInverse(fact[Y], MOD)) % MOD; // Total permutation = // (X + Y + Z)! (X! * Y! * Z!) ans = (ans * modInverse(fact[Z], MOD)) % MOD; // Printing answer System.out.print(ans - 6 + " " ); } System.out.println(); } public static void main(String[] args) { // Test Case 1 int [][] Q = { { 1 , 1 , 1 }, { 1 , 2 , 1 }, { 2 , 2 , 1 } }; int N = 3 ; // Function Call findWays(Q, N); // Test Case 2 int [][] Q1 = { { 2 , 3 , 5 }, { 5 , 6 , 7 }, { 8 , 9 , 10 } }; int N1 = 3 ; // Function Call findWays(Q1, N1); } } // This code is contributed by lokesh. |
Python3
# Python3 code to implement the approach MOD = int ( 1e9 + 7 ) # 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 a # under modulo M # Assumption: M is prime def modInverse(A: int , M: int ) - > int : # If a and m are relatively prime, # then modulo inverse is # a^(m-2) mode m return power(A, M - 2 , M) # Function to print Count ways def findWays(Q: list , M: int ): # Precomputing factorial array fact = [ 0 for _ in range ( 100001 )] # Factorial of 1 is 1 fact[ 1 ] = 1 # Finding factorial of all 1e5 numbers for i in range ( 2 , int ( 1e5 ) + 1 ): fact[i] = (fact[i - 1 ] * i) % MOD # Traversing for each query for i in range (M): # X, Y and Z for i'th query X, Y, Z = Q[i] # Total permutation = # (X + Y + Z)! / X! ans = (fact[X + Y + Z] * modInverse(fact[X], MOD)) % MOD # Total permutation = # (X + Y + Z)! / (X! * Y!) ans = (ans * modInverse(fact[Y], MOD)) % MOD # Total permutation = # (X + Y + Z)! (X! * Y! * Z!) ans = (ans * modInverse(fact[Z], MOD)) % MOD # Printing answer print (ans - 6 , end = ' ' ) print () # Driver Code if __name__ = = "__main__" : # Test Case 1 Q = [[ 1 , 1 , 1 ], [ 1 , 2 , 1 ], [ 2 , 2 , 1 ]] N = 3 # Function Call findWays(Q, N) # Test Case 2 Q1 = [[ 2 , 3 , 5 ], [ 5 , 6 , 7 ], [ 8 , 9 , 10 ]] N1 = 3 # Function Call findWays(Q1, N1) # This code is contributed by lokeshpotta20. |
C#
// C# code to implement the approach using System; using System.Linq; using System.Collections.Generic; public class GFG { public const long MOD = ( long )1e9 + 7; // To compute x raised to power 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 a // under modulo M // Assumption: M is prime static long modInverse( long A, long M) { // If a and m are relatively prime, // then modulo inverse is // a^(m-2) mode m return power(A, M - 2, M); } // Function to print Count ways given // characters arranged in row so that // at least on character is separated // from character of same type for each M // queries. static void findWays( int [, ] Q, int M) { // Precomputing factorial array long [] fact = new long [100001]; // Factorial of 1 is 1 fact[1] = 1; // Finding factorial of all 1e5 numbers for ( int i = 2; i <= 1e5; i++) { fact[i] = (fact[i - 1] * i) % MOD; } // Traversing for each query for ( int i = 0; i < M; i++) { // X, Y and Z for i'th query int X = Q[i, 0], Y = Q[i, 1], Z = Q[i, 2]; // Total permutation = // (X + Y + Z)! / X! long ans = (fact[X + Y + Z] * modInverse(fact[X], MOD)) % MOD; // Total permutation = // (X + Y + Z)! / (X! * Y!) ans = (ans * modInverse(fact[Y], MOD)) % MOD; // Total permutation = // (X + Y + Z)! (X! * Y! * Z!) ans = (ans * modInverse(fact[Z], MOD)) % MOD; // Printing answer Console.Write(ans - 6 + " " ); } Console.WriteLine(); } static public void Main() { // Code // Test Case 1 int [, ] Q = { { 1, 1, 1 }, { 1, 2, 1 }, { 2, 2, 1 } }; int N = 3; // Function Call findWays(Q, N); // Test Case 2 int [, ] Q1 = { { 2, 3, 5 }, { 5, 6, 7 }, { 8, 9, 10 } }; int N1 = 3; // Function Call findWays(Q1, N1); } } // This code is contributed by lokeshmvs21. |
Javascript
// Javascript code to implement the approach const MOD = BigInt(1e9 + 7); // 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 a // under modulo M // Assumption: M is prime function modInverse(A, M) { // If a and m are relatively prime, // then modulo inverse is // a^(m-2) mode m return power(A, M - 2n, M); } // Function to print Count ways function findWays(Q, M) { // Precomputing factorial array const fact = new Array(100001).fill(0n); // Factorial of 1 is 1 fact[1] = 1n; // Finding factorial of all 1e5 numbers for (let i = 2; i <= 1e5; i++) { fact[i] = (fact[i - 1] * BigInt(i)) % MOD; } // Traversing for each query for (let i = 0; i < M; i++) { // X, Y and Z for i'th query const [X, Y, Z] = Q[i]; // Total permutation = // (X + Y + Z)! / X! let ans = (fact[X + Y + Z] * modInverse(fact[X], MOD)) % MOD; // Total permutation = // (X + Y + Z)! / (X! * Y!) ans = (ans * modInverse(fact[Y], MOD)) % MOD; // Total permutation = // (X + Y + Z)! (X! * Y! * Z!) ans = (ans * modInverse(fact[Z], MOD)) % MOD; // Printing answer process.stdout.write((ans - 6n) + ' '); } process.stdout.write(' \n'); } // Test Case 1 const Q = [[1, 1, 1], [1, 2, 1], [2, 2, 1]]; const N = 3; // Function Call findWays(Q, N); // Test Case 2 const Q1 = [[2, 3, 5], [5, 6, 7], [8, 9, 10]]; const N1 = 3; // Function Call findWays(Q1, N1); |
0 6 24 2514 14702682 86086909
Time Complexity: O(M), Where M is the number of queries.
Auxiliary Space: O(M)
Related Articles:
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!