Queries of nCr%p in O(1) time complexity
Last Updated :
19 Jan, 2022
Given Q queries and P where P is a prime number, each query has two numbers N and R and the task is to calculate nCr mod p.
Constraints:
N <= 106
R <= 106
p is a prime number
Examples:
Input:
Q = 2 p = 1000000007
1st query: N = 15, R = 4
2nd query: N = 20, R = 3
Output:
1st query: 1365
2nd query: 1140
15!/(4!*(15-4)!)%1000000007 = 1365
20!/(20!*(20-3)!)%1000000007 = 1140
A naive approach is to calculate nCr using formulae by applying modular operations at any time. Hence time complexity will be O(q*n).
A better approach is to use fermat little theorem. According to it nCr can also be written as (n!/(r!*(n-r)!) ) mod which is equivalent to (n!*inverse(r!)*inverse((n-r)!) ) mod p. So, precomputing factorial of numbers from 1 to n will allow queries to be answered in O(log n). The only calculation that needs to be done is calculating inverse of r! and (n-r)!. Hence overall complexity will be q*( log(n)) .
A efficient approach will be to reduce the better approach to an efficient one by precomputing the inverse of factorials. Precompute inverse of factorial in O(n) time and then queries can be answered in O(1) time. Inverse of 1 to N natural number can be computed in O(n) time using Modular multiplicative inverse. Using recursive definition of factorial, the following can be written:
n! = n * (n-1) !
taking inverse on both side
inverse( n! ) = inverse( n ) * inverse( (n-1)! )
Since N's maximum value is 106, precomputing values till 106 will do.
Below is the implementation of the above approach:
C++
// C++ program to answer queries
// of nCr in O(1) time.
#include <bits/stdc++.h>
#define ll long long
const int N = 1000001;
using namespace std;
// array to store inverse of 1 to N
ll factorialNumInverse[N + 1];
// array to precompute inverse of 1! to N!
ll naturalNumInverse[N + 1];
// array to store factorial of first N numbers
ll fact[N + 1];
// Function to precompute inverse of numbers
void InverseofNumber(ll p)
{
naturalNumInverse[0] = naturalNumInverse[1] = 1;
for (int i = 2; i <= N; i++)
naturalNumInverse[i] = naturalNumInverse[p % i] * (p - p / i) % p;
}
// Function to precompute inverse of factorials
void InverseofFactorial(ll p)
{
factorialNumInverse[0] = factorialNumInverse[1] = 1;
// precompute inverse of natural numbers
for (int i = 2; i <= N; i++)
factorialNumInverse[i] = (naturalNumInverse[i] * factorialNumInverse[i - 1]) % p;
}
// Function to calculate factorial of 1 to N
void factorial(ll p)
{
fact[0] = 1;
// precompute factorials
for (int i = 1; i <= N; i++) {
fact[i] = (fact[i - 1] * i) % p;
}
}
// Function to return nCr % p in O(1) time
ll Binomial(ll N, ll R, ll p)
{
// n C r = n!*inverse(r!)*inverse((n-r)!)
ll ans = ((fact[N] * factorialNumInverse[R])
% p * factorialNumInverse[N - R])
% p;
return ans;
}
// Driver Code
int main()
{
// Calling functions to precompute the
// required arrays which will be required
// to answer every query in O(1)
ll p = 1000000007;
InverseofNumber(p);
InverseofFactorial(p);
factorial(p);
// 1st query
ll N = 15;
ll R = 4;
cout << Binomial(N, R, p) << endl;
// 2nd query
N = 20;
R = 3;
cout << Binomial(N, R, p) << endl;
return 0;
}
Java
// Java program to answer queries
// of nCr in O(1) time
import java.io.*;
class GFG{
static int N = 1000001;
// Array to store inverse of 1 to N
static long[] factorialNumInverse = new long[N + 1];
// Array to precompute inverse of 1! to N!
static long[] naturalNumInverse = new long[N + 1];
// Array to store factorial of first N numbers
static long[] fact = new long[N + 1];
// Function to precompute inverse of numbers
public static void InverseofNumber(int p)
{
naturalNumInverse[0] = naturalNumInverse[1] = 1;
for(int i = 2; i <= N; i++)
naturalNumInverse[i] = naturalNumInverse[p % i] *
(long)(p - p / i) % p;
}
// Function to precompute inverse of factorials
public static void InverseofFactorial(int p)
{
factorialNumInverse[0] = factorialNumInverse[1] = 1;
// Precompute inverse of natural numbers
for(int i = 2; i <= N; i++)
factorialNumInverse[i] = (naturalNumInverse[i] *
factorialNumInverse[i - 1]) % p;
}
// Function to calculate factorial of 1 to N
public static void factorial(int p)
{
fact[0] = 1;
// Precompute factorials
for(int i = 1; i <= N; i++)
{
fact[i] = (fact[i - 1] * (long)i) % p;
}
}
// Function to return nCr % p in O(1) time
public static long Binomial(int N, int R, int p)
{
// n C r = n!*inverse(r!)*inverse((n-r)!)
long ans = ((fact[N] * factorialNumInverse[R]) %
p * factorialNumInverse[N - R]) % p;
return ans;
}
// Driver code
public static void main (String[] args)
{
// Calling functions to precompute the
// required arrays which will be required
// to answer every query in O(1)
int p = 1000000007;
InverseofNumber(p);
InverseofFactorial(p);
factorial(p);
// 1st query
int n = 15;
int R = 4;
System.out.println(Binomial(n, R, p));
// 2nd query
n = 20;
R = 3;
System.out.println(Binomial(n, R, p));
}
}
// This code is contributed by RohitOberoi
Python3
# Python3 program to answer queries
# of nCr in O(1) time.
N = 1000001
# array to store inverse of 1 to N
factorialNumInverse = [None] * (N + 1)
# array to precompute inverse of 1! to N!
naturalNumInverse = [None] * (N + 1)
# array to store factorial of
# first N numbers
fact = [None] * (N + 1)
# Function to precompute inverse of numbers
def InverseofNumber(p):
naturalNumInverse[0] = naturalNumInverse[1] = 1
for i in range(2, N + 1, 1):
naturalNumInverse[i] = (naturalNumInverse[p % i] *
(p - int(p / i)) % p)
# Function to precompute inverse
# of factorials
def InverseofFactorial(p):
factorialNumInverse[0] = factorialNumInverse[1] = 1
# precompute inverse of natural numbers
for i in range(2, N + 1, 1):
factorialNumInverse[i] = (naturalNumInverse[i] *
factorialNumInverse[i - 1]) % p
# Function to calculate factorial of 1 to N
def factorial(p):
fact[0] = 1
# precompute factorials
for i in range(1, N + 1):
fact[i] = (fact[i - 1] * i) % p
# Function to return nCr % p in O(1) time
def Binomial(N, R, p):
# n C r = n!*inverse(r!)*inverse((n-r)!)
ans = ((fact[N] * factorialNumInverse[R])% p *
factorialNumInverse[N - R])% p
return ans
# Driver Code
if __name__ == '__main__':
# Calling functions to precompute the
# required arrays which will be required
# to answer every query in O(1)
p = 1000000007
InverseofNumber(p)
InverseofFactorial(p)
factorial(p)
# 1st query
N = 15
R = 4
print(Binomial(N, R, p))
# 2nd query
N = 20
R = 3
print(Binomial(N, R, p))
# This code is contributed by
# Surendra_Gangwar
C#
// C# program to answer queries
// of nCr in O(1) time
using System;
class GFG{
static int N = 1000001;
// Array to store inverse of 1 to N
static long[] factorialNumInverse = new long[N + 1];
// Array to precompute inverse of 1! to N!
static long[] naturalNumInverse = new long[N + 1];
// Array to store factorial of first N numbers
static long[] fact = new long[N + 1];
// Function to precompute inverse of numbers
static void InverseofNumber(int p)
{
naturalNumInverse[0] = naturalNumInverse[1] = 1;
for(int i = 2; i <= N; i++)
naturalNumInverse[i] = naturalNumInverse[p % i] *
(long)(p - p / i) % p;
}
// Function to precompute inverse of factorials
static void InverseofFactorial(int p)
{
factorialNumInverse[0] = factorialNumInverse[1] = 1;
// Precompute inverse of natural numbers
for(int i = 2; i <= N; i++)
factorialNumInverse[i] = (naturalNumInverse[i] *
factorialNumInverse[i - 1]) % p;
}
// Function to calculate factorial of 1 to N
static void factorial(int p)
{
fact[0] = 1;
// Precompute factorials
for(int i = 1; i <= N; i++)
{
fact[i] = (fact[i - 1] * (long)i) % p;
}
}
// Function to return nCr % p in O(1) time
static long Binomial(int N, int R, int p)
{
// n C r = n!*inverse(r!)*inverse((n-r)!)
long ans = ((fact[N] * factorialNumInverse[R]) %
p * factorialNumInverse[N - R]) % p;
return ans;
}
// Driver code
static void Main()
{
// Calling functions to precompute the
// required arrays which will be required
// to answer every query in O(1)
int p = 1000000007;
InverseofNumber(p);
InverseofFactorial(p);
factorial(p);
// 1st query
int n = 15;
int R = 4;
Console.WriteLine(Binomial(n, R, p));
// 2nd query
n = 20;
R = 3;
Console.WriteLine(Binomial(n, R, p));
}
}
// This code is contributed by divyeshrabadiya07
JavaScript
<script>
// Javascript program to answer queries
// of nCr in O(1) time.
var N = 1000001;
// array to store inverse of 1 to N
factorialNumInverse = Array(N+1).fill(0);
// array to precompute inverse of 1! to N!
naturalNumInverse = Array(N+1).fill(0);
// array to store factorial of first N numbers
fact = Array(N+1).fill(0);
// Function to precompute inverse of numbers
function InverseofNumber(p)
{
naturalNumInverse[0] = naturalNumInverse[1] = 1;
for (var i = 2; i <= N; i++)
naturalNumInverse[i] = (naturalNumInverse[p % i] * (p - parseInt(p / i))) % p;
}
// Function to precompute inverse of factorials
function InverseofFactorial(p)
{
factorialNumInverse[0] = factorialNumInverse[1] = 1;
// precompute inverse of natural numbers
for (var i = 2; i <= N; i++)
factorialNumInverse[i] = ((naturalNumInverse[i] * factorialNumInverse[i - 1])) % p;
}
// Function to calculate factorial of 1 to N
function factorial(p)
{
fact[0] = 1;
// precompute factorials
for (var i = 1; i <= N; i++) {
fact[i] = (fact[i - 1] * i) % p;
}
}
// Function to return nCr % p in O(1) time
function Binomial(N, R, p)
{
// n C r = n!*inverse(r!)*inverse((n-r)!)
var ans = ((((fact[N] * factorialNumInverse[R])% p) * factorialNumInverse[N - R]))% p;
return ans;
}
// Driver Code
// Calling functions to precompute the
// required arrays which will be required
// to answer every query in O(1)
p = 100000007;
InverseofNumber(p);
InverseofFactorial(p);
factorial(p);
// 1st query
N = 15;
R = 4;
document.write(Binomial(N, R, p)+"<br>")
// 2nd query
N = 20;
R = 3;
document.write(Binomial(N, R, p));
// This code is contributed by noob2000.
</script>
Time Complexity: O(N) for precomputing and O(1) for every query.
Auxiliary Space: O(N)
Similar Reads
PreComputation Technique on Arrays
Precomputation refers to the process of pre-calculating and storing the results of certain computations or data structures(array in this case) in advance, in order to speed up the execution time of a program. This can be useful in situations where the same calculations are needed multiple times, as
15 min read
Queries for the product of first N factorials
Given Q[] queries where each query consists of an integer N, the task is to find the product of first N factorials for each of the query. Since the result could be large, compute it modulo 109 + 7.Examples: Input: Q[] = {4, 5} Output: 288 34560 Query 1: 1! * 2! * 3! * 4! = 1 * 2 * 6 * 24 = 288 Query
7 min read
Range sum queries without updates
Given an array arr of integers of size n. We need to compute the sum of elements from index i to index j. The queries consisting of i and j index values will be executed multiple times.Examples: Input : arr[] = {1, 2, 3, 4, 5} i = 1, j = 3 i = 2, j = 4Output : 9 12 Input : arr[] = {1, 2, 3, 4, 5} i
6 min read
Range Queries for Frequencies of array elements
Given an array of n non-negative integers. The task is to find frequency of a particular element in the arbitrary range of array[]. The range is given as positions (not 0 based indexes) in array. There can be multiple queries of given type. Examples: Input : arr[] = {2, 8, 6, 9, 8, 6, 8, 2, 11}; lef
13 min read
Count Primes in Ranges
Given a 2d array queries[][] of size n, where each query queries[i] contain 2 elements [l, r], your task is to find the count of number of primes in inclusive range [l, r]Examples: Input: queries[][] = [ [1, 10], [5, 10], [11, 20] ]Output: 4 2 4Explanation: For query 1, number of primes in range [1,
12 min read
Check in binary array the number represented by a subarray is odd or even
Given an array such that all its terms is either 0 or 1.You need to tell the number represented by a subarray a[l..r] is odd or even Examples : Input : arr = {1, 1, 0, 1} l = 1, r = 3 Output : odd number represented by arr[l...r] is 101 which 5 in decimal form which is odd Input : arr = {1, 1, 1, 1}
4 min read
GCDs of given index ranges in an Array
Given an array arr[] of size N and Q queries of type {qs, qe} where qs and qe denote the starting and ending index of the query, the task is to find the GCD of all the numbers in the range. Examples: Input: arr[] = {2, 3, 60, 90, 50};Index Ranges: {1, 3}, {2, 4}, {0, 2}Output: GCDs of given ranges a
14 min read
Mean of range in array
Given an array arr[] of n integers and q queries represented by an array queries[][], where queries[i][0] = l and queries[i][1] = r. For each query, the task is to calculate the mean of elements in the range l to r and return its floor value. Examples: Input: arr[] = [3, 7, 2, 8, 5] queries[][] = [[
12 min read
Difference Array | Range update query in O(1)
You are given an integer array arr[] and a list of queries. Each query is represented as a list of integers where:[1, l, r, x]: Adds x to all elements from arr[l] to arr[r] (inclusive).[2]: Prints the current state of the array.You need to perform the queries in order.Examples : Input: arr[] = [10,
10 min read
Range sum query using Sparse Table
We have an array arr[]. We need to find the sum of all the elements in the range L and R where 0 <= L <= R <= n-1. Consider a situation when there are many range queries. Examples: Input : 3 7 2 5 8 9 query(0, 5) query(3, 5) query(2, 4) Output : 34 22 15Note : array is 0 based indexed and q
8 min read