Count number of pairs of arrays (a, b) such that a[i] <= b[i]
Last Updated :
23 Mar, 2024
Given two integers n and m, the task is to count the number of pairs of arrays (a, b) where both arrays have a length of m, contain integers between 1 and n (inclusive), and satisfy the conditions that each element in array a is less than or equal to the corresponding element in array b for all indices from 1 to m (i.e, a[i] <= b[i]) Additionally, array a must be sorted in non-decreasing order, array b must be sorted in non-increasing order, and the result should be printed modulo 10^9 + 7.
Example:
Input: n = 2, m = 2
Output: 5
Explanation: There are 5 suitable arrays:
- a={1,1}, b={2,2}
- a={1,2}, b={2,2}
- a={2,2}, b={2,2}
- a={1,1}, b={2,1}
- a={1,1}, b={1,1}
Input: n = 10, m = 1
Output: 55
Approach:
This is a combinatorics problem that can be solved using the concept of “Stars and Bars”.
Imagine you have n items (stars) and you want to distribute them into 2m bins (bars). Each bin represents a position in the array a or b. The problem is equivalent to arranging these stars and bars in a line.
The total number of ways to arrange n stars and 2m bars is given by the formula for combinations:
C(n+2m,2m)= (n + 2m)! / (n!(2m)!)
However, since we have n items and 2m bins, and we subtract 1 because the problem states that each element of both arrays is an integer between 1 and n (inclusive), the formula becomes:
C(2m+n-1,2m)= (2m + n – 1)! / (n – 1) ! (2m)!
This gives the total number of ways to distribute the items. However, this count includes duplicates due to the sorted order of a and b. To adjust for these duplicates, we divide by (n-1)! and (2m)!.
Steps-by-step approach:
- Create a power function to efficiently calculate the modular exponentiation of a number.
- Calculate factorials for a range of numbers using the calculateFactorial() function.
- Implement an inverse function to find the modular inverse of a number.
- In the main function:
- Precompute factorials.
- Calculate the answer (2m + n – 1)! represents the total arrangements of elements in arrays a and b
- Dividing answer by factorial(n-1):
- This step accounts for the duplicates introduced by the non-decreasing order in array ‘a’. We divide by (n-1)! to eliminate arrangements that would be considered the same due to the sorted order of ‘a’.
- Dividing by factorial(2m)!:
- Similar to the above step, this division is for the duplicates introduced by the non-increasing order in array ‘b’. We divide by (2m)! to remove arrangements that would be considered equivalent due to the sorted order of ‘b’.
- Print the answer modulo 1e9 + 7.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
// Define the type long long as ll for convenience
typedef long long ll;
// Constants for the modulo operation and the maximum size
// of the array
const ll MODULO = 1e9 + 7;
const ll MAX_SIZE = 2005;
// Function to calculate the power of a number with modulo
ll power(ll base, ll exponent, ll modulo)
{
base %= modulo;
ll result = 1;
while (exponent > 0) {
if (exponent & 0x1)
result = (result * base) % modulo;
base = (base * base) % modulo;
exponent >>= 1;
}
return result;
}
// Array to store the factorial of numbers
ll factorial[MAX_SIZE];
// Function to calculate the factorial of numbers
void calculateFactorial()
{
factorial[0] = factorial[1] = 1LL;
for (int i = 2; i < MAX_SIZE; i++)
factorial[i] = factorial[i - 1] * i % MODULO;
}
// Function to calculate the inverse of a number with modulo
ll inverse(ll x) { return power(x, MODULO - 2, MODULO); }
int main()
{
// Calculate the factorial of numbers
calculateFactorial();
// Variables to store the input numbers and the answer
ll n = 2, m = 2;
// Calculate the answer
ll answer = factorial[2 * m + n - 1];
// Dividing by (n-1)! and (2m)!: Adjusts for duplicates
// due to sorted orders of 'a' and 'b'.
answer = (answer * inverse(factorial[n - 1])) % MODULO;
answer = (answer * inverse(factorial[2 * m])) % MODULO;
// Print the answer
cout << answer;
return 0;
}
Java
import java.util.Arrays;
public class Main {
// Define the type long long as ll for convenience
static class Pair {
long first, second;
Pair(long first, long second) {
this.first = first;
this.second = second;
}
}
// Constants for the modulo operation and the maximum size
// of the array
static final long MODULO = 1000000007;
static final int MAX_SIZE = 2005;
// Function to calculate the power of a number with modulo
static long power(long base, long exponent, long modulo) {
base %= modulo;
long result = 1;
while (exponent > 0) {
if ((exponent & 1) == 1)
result = (result * base) % modulo;
base = (base * base) % modulo;
exponent >>= 1;
}
return result;
}
// Array to store the factorial of numbers
static long[] factorial = new long[MAX_SIZE];
// Function to calculate the factorial of numbers
static void calculateFactorial() {
factorial[0] = factorial[1] = 1L;
for (int i = 2; i < MAX_SIZE; i++)
factorial[i] = (factorial[i - 1] * i) % MODULO;
}
// Function to calculate the inverse of a number with modulo
static long inverse(long x) {
return power(x, MODULO - 2, MODULO);
}
public static void main(String[] args) {
// Calculate the factorial of numbers
calculateFactorial();
// Variables to store the input numbers and the answer
long n = 2, m = 2;
// Calculate the answer
long answer = factorial[(int) (2 * m + n - 1)];
// Dividing by (n-1)! and (2m)!: Adjusts for duplicates
// due to sorted orders of 'a' and 'b'.
answer = (answer * inverse(factorial[(int) (n - 1)])) % MODULO;
answer = (answer * inverse(factorial[(int) (2 * m)])) % MODULO;
// Print the answer
System.out.println(answer);
}
}
C#
using System;
class Program
{
// Define the type long long as ll for convenience
public static long Power(long baseValue, long exponent, long modulo)
{
baseValue %= modulo;
long result = 1;
while (exponent > 0)
{
if ((exponent & 0x1) == 1)
result = (result * baseValue) % modulo;
baseValue = (baseValue * baseValue) % modulo;
exponent >>= 1;
}
return result;
}
// Constants for the modulo operation and the maximum size
// of the array
public const long MODULO = 1000000007;
public const int MAX_SIZE = 2005;
// Array to store the factorial of numbers
public static long[] Factorial;
// Function to calculate the factorial of numbers
public static void CalculateFactorial()
{
Factorial = new long[MAX_SIZE];
Factorial[0] = Factorial[1] = 1L;
for (int i = 2; i < MAX_SIZE; i++)
Factorial[i] = (Factorial[i - 1] * i) % MODULO;
}
// Function to calculate the inverse of a number with modulo
public static long Inverse(long x) => Power(x, MODULO - 2, MODULO);
static void Main()
{
// Calculate the factorial of numbers
CalculateFactorial();
// Variables to store the input numbers and the answer
long n = 2, m = 2;
// Calculate the answer
long answer = Factorial[2 * m + n - 1];
// Dividing by (n-1)! and (2m)!: Adjusts for duplicates
// due to sorted orders of 'a' and 'b'.
answer = (answer * Inverse(Factorial[n - 1])) % MODULO;
answer = (answer * Inverse(Factorial[2 * m])) % MODULO;
// Print the answer
Console.WriteLine(answer);
}
}
JavaScript
// Define the modulo operation
const MODULO = BigInt(1e9 + 7);
const MAX_SIZE = 2005;
// Function to calculate the power of a number with modulo
function power(base, exponent, modulo) {
base = base % modulo;
let result = BigInt(1);
while (exponent > BigInt(0)) {
if (exponent & BigInt(1))
result = (result * base) % modulo;
base = (base * base) % modulo;
exponent >>= BigInt(1);
}
return result;
}
// Array to store the factorial of numbers
let factorial = new Array(MAX_SIZE);
// Function to calculate the factorial of numbers
function calculateFactorial() {
factorial[0] = factorial[1] = BigInt(1);
for (let i = 2; i < MAX_SIZE; i++)
factorial[i] = (factorial[i - 1] * BigInt(i)) % MODULO;
}
// Function to calculate the inverse of a number with modulo
function inverse(x) { return power(x, MODULO - BigInt(2), MODULO); }
// Calculate the factorial of numbers
calculateFactorial();
// Variables to store the input numbers and the answer
let n = BigInt(2), m = BigInt(2);
// Calculate the answer
let answer = factorial[BigInt(2) * m + n - BigInt(1)];
// Dividing by (n-1)! and (2m)!: Adjusts for duplicates
// due to sorted orders of 'a' and 'b'.
answer = (answer * inverse(BigInt(factorial[BigInt(2) * m]))) % MODULO;
answer = (answer * inverse(BigInt(factorial[n - BigInt(1)]))) % MODULO;
// Print the answer
console.log(answer.toString());
Python3
# Function to calculate the power of a number with modulo
def power(base, exponent, modulo):
base %= modulo
result = 1
while exponent > 0:
if exponent & 1:
result = (result * base) % modulo
base = (base * base) % modulo
exponent >>= 1
return result
# Constants for the modulo operation and the maximum size of the array
MODULO = 1000000007
MAX_SIZE = 2005
# Array to store the factorial of numbers
factorial = [0] * MAX_SIZE
# Function to calculate the factorial of numbers
def calculate_factorial():
factorial[0] = factorial[1] = 1
for i in range(2, MAX_SIZE):
factorial[i] = (factorial[i - 1] * i) % MODULO
# Function to calculate the inverse of a number with modulo
def inverse(x):
return power(x, MODULO - 2, MODULO)
# Calculate the factorial of numbers
calculate_factorial()
# Variables to store the input numbers and the answer
n = 2
m = 2
# Calculate the answer
answer = factorial[2 * m + n - 1]
# Dividing by (n-1)! and (2m)! to adjust for duplicates
# due to sorted orders of 'a' and 'b'.
answer = (answer * inverse(factorial[n - 1])) % MODULO
answer = (answer * inverse(factorial[2 * m])) % MODULO
# Print the answer
print(answer)
Time Complexity: O(MAX_SIZE * log(exponent)), Computing factorials involves iterating up to MAX_SIZE, and modular exponentiation has a time complexity proportional to log(exponent).
Auxiliary Space: O(MAX_SIZE), The program uses an array (factorial) with a fixed size (MAX_SIZE).
Share your thoughts in the comments
Please Login to comment...