An application on Bertrand’s ballot theorem

Given the number of ‘X’ and ‘Y’ in a string which consists of characters from the set {‘X’, ‘Y’}, the task is to find the number of permutations which satisfy the condition where every sub-string of the permutation starting from the first character has count(‘X’) > count(‘Y’). Print the answer modulo 1000000007. Note that the number of ‘X’ will always be greater than number of ‘Y’ in the given string.

Examples:

Input: X = 2, Y = 1
Output: 1
The possible distributions are “XYX”, “XXY” and “YXX”
Distribution 1: Till 1st index (X = 1, Y = 0), till 2nd index (X = 1, Y = 1) and till 3rd index (X = 2, Y = 1). Number of X isn’t always greater than Y so this distribution is not valid.
Distribution 2: 1st index (X = 1, Y = 0), 2nd index (X = 2, Y = 0) and 3rd index (X = 2, Y = 1). This is a valid distribution as X is always greater than Y.
Distribution 3: 1st index (X = 0, Y = 1), 2nd index (X = 1, Y = 1) and 3rd index (X = 2, Y = 1). Invalid distribution.

Input: X = 3, Y = 1
Output: 1

Approach: This type of problem can be solved by Bertrand’s Ballot Theorem. Out of all possible distributions, the probability that X always remains in the lead is (X – Y) / (X + Y). And the total number of distributions are (X + Y)! / (X! * Y!). Hence the distributions in which X always has the lead are (X + Y – 1)! * (X – Y) / (X! * Y!).
For calculating (X + Y – 1)! * (X – Y) / (X! * Y!), we need to calculate multiplicative modular inverse of X! and thus similarly for Y. Since 1000000007 is a prime, according to Fermat’s Little Theorem : (1 / X!) % 1000000007 = ((X!)(1000000007 – 2)) % 1000000007. Similar result also holds for Y.

Below is the implementation of the above approach:

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
#define ll long long
  
ll mod = 1000000007;
ll arr[1000001] = { 0 };
  
// Function to calculate factorial
// of a number mod 1000000007
void cal_factorial()
{
    arr[0] = 1;
  
    // Factorial of i = factorial of (i - 1) * i;
    for (int i = 1; i <= 1000000; i++) {
  
        // Taking mod along with calculation.
        arr[i] = (arr[i - 1] * i) % mod;
    }
}
  
// Function for modular exponentiation
ll mod_exponent(ll num, ll p)
{
  
    if (p == 0)
        return 1;
  
    // If p is odd
    if (p & 1) {
        return ((num % mod)
                * (mod_exponent((num * num) % mod, p / 2))
                % mod)
               % mod;
    }
  
    // If p is even
    else if (!(p & 1))
        return (mod_exponent((num * num) % mod, p / 2))
               % mod;
}
  
// Function to return the count of
// required permutations
ll getCount(ll x, ll y)
{
    ll ans = arr[x + y - 1];
  
    // Calculating multiplicative modular inverse
    // for x! and multiplying with ans
    ans *= mod_exponent(arr[x], mod - 2);
    ans %= mod;
  
    // Calculating multiplicative modular inverse
    // for y! and multiplying with ans
    ans *= mod_exponent(arr[y], mod - 2);
    ans %= mod;
  
    ans *= (x - y);
    ans %= mod;
    return ans;
}
  
// Driver code
int main()
{
  
    // Pre-compute factorials
    cal_factorial();
  
    ll x = 3, y = 1;
    cout << getCount(x, y);
  
    return 0;
}

chevron_right


Output:

2


My Personal Notes arrow_drop_up