Open In App

Count number of pairs of arrays (a, b) such that a[i] <= b[i]

Last Updated : 23 Mar, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

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)

Output
5

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).



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads