TheAlgorithms/C++ 1.0.0
All the algorithms implemented in C++
Loading...
Searching...
No Matches
ncr_modulo_p.cpp File Reference

This program aims at calculating nCr modulo p. More...

#include <cassert>
#include <iostream>
#include <vector>
Include dependency graph for ncr_modulo_p.cpp:

Go to the source code of this file.

Classes

class  math::ncr_modulo_p::NCRModuloP
 Class which contains all methods required for calculating nCr mod p. More...
 

Namespaces

namespace  math
 for assert
 
namespace  ncr_modulo_p
 Functions for nCr modulo p implementation.
 
namespace  utils
 this namespace contains the definitions of the functions called from the class math::ncr_modulo_p::NCRModuloP
 

Functions

int64_t math::ncr_modulo_p::utils::gcdExtended (const int64_t &a, const int64_t &b, int64_t &x, int64_t &y)
 finds the values x and y such that a*x + b*y = gcd(a,b)
 
int64_t math::ncr_modulo_p::utils::modInverse (const int64_t &a, const int64_t &m)
 
static void tests ()
 tests math::ncr_modulo_p::NCRModuloP
 
void example ()
 example showing the usage of the math::ncr_modulo_p::NCRModuloP class
 
int main ()
 

Detailed Description

This program aims at calculating nCr modulo p.

nCr is defined as n! / (r! * (n-r)!) where n! represents factorial of n. In many cases, the value of nCr is too large to fit in a 64 bit integer. Hence, in competitive programming, there are many problems or subproblems to compute nCr modulo p where p is a given number.

Author
Kaustubh Damania

Definition in file ncr_modulo_p.cpp.

Function Documentation

◆ example()

void example ( )

example showing the usage of the math::ncr_modulo_p::NCRModuloP class

Definition at line 175 of file ncr_modulo_p.cpp.

175 {
176 const int64_t size = 1e6 + 1;
177 const int64_t p = 1e9 + 7;
178
179 // the ncrObj contains the precomputed values of factorials modulo p for
180 // values from 0 to size
181 const auto ncrObj = math::ncr_modulo_p::NCRModuloP(size, p);
182
183 // having the ncrObj we can efficiently query the values of (n C r)%p
184 // note that time of the computation does not depend on size
185 for (int i = 0; i <= 7; i++) {
186 std::cout << 6 << "C" << i << " mod " << p << " = " << ncrObj.ncr(6, i)
187 << "\n";
188 }
189}
Class which contains all methods required for calculating nCr mod p.

◆ gcdExtended()

int64_t math::ncr_modulo_p::utils::gcdExtended ( const int64_t & a,
const int64_t & b,
int64_t & x,
int64_t & y )

finds the values x and y such that a*x + b*y = gcd(a,b)

Parameters
[in]athe first input of the gcd
[in]athe second input of the gcd
[out]xthe Bézout coefficient of a
[out]ythe Bézout coefficient of b
Returns
the gcd of a and b

Definition at line 44 of file ncr_modulo_p.cpp.

45 {
46 if (a == 0) {
47 x = 0;
48 y = 1;
49 return b;
50 }
51
52 int64_t x1 = 0, y1 = 0;
53 const int64_t gcd = gcdExtended(b % a, a, x1, y1);
54
55 x = y1 - (b / a) * x1;
56 y = x1;
57 return gcd;
58}
int gcd(int num1, int num2)
int64_t gcdExtended(const int64_t &a, const int64_t &b, int64_t &x, int64_t &y)
finds the values x and y such that a*x + b*y = gcd(a,b)

◆ main()

int main ( void )

Definition at line 191 of file ncr_modulo_p.cpp.

191 {
192 tests();
193 example();
194 return 0;
195}
static void tests()
tests math::ncr_modulo_p::NCRModuloP
void example()
example showing the usage of the math::ncr_modulo_p::NCRModuloP class

◆ modInverse()

int64_t math::ncr_modulo_p::utils::modInverse ( const int64_t & a,
const int64_t & m )

Find modular inverse of a modulo m i.e. a number x such that (a*x)m = 1

Parameters
[in]athe number for which the modular inverse is queried
[in]mthe modulus
Returns
the inverce of a modulo m, if it exists, -1 otherwise

Definition at line 66 of file ncr_modulo_p.cpp.

66 {
67 int64_t x = 0, y = 0;
68 const int64_t g = gcdExtended(a, m, x, y);
69 if (g != 1) { // modular inverse doesn't exist
70 return -1;
71 } else {
72 return ((x + m) % m);
73 }
74}
double g(double x)
Another test function.

◆ tests()

static void tests ( )
static

tests math::ncr_modulo_p::NCRModuloP

Definition at line 142 of file ncr_modulo_p.cpp.

142 {
143 struct TestCase {
144 const int64_t size;
145 const int64_t p;
146 const int64_t n;
147 const int64_t r;
148 const int64_t expected;
149
150 TestCase(const int64_t size, const int64_t p, const int64_t n,
151 const int64_t r, const int64_t expected)
152 : size(size), p(p), n(n), r(r), expected(expected) {}
153 };
154 const std::vector<TestCase> test_cases = {
155 TestCase(60000, 1000000007, 52323, 26161, 224944353),
156 TestCase(20, 5, 6, 2, 30 % 5),
157 TestCase(100, 29, 7, 3, 35 % 29),
158 TestCase(1000, 13, 10, 3, 120 % 13),
159 TestCase(20, 17, 1, 10, 0),
160 TestCase(45, 19, 23, 1, 23 % 19),
161 TestCase(45, 19, 23, 0, 1),
162 TestCase(45, 19, 23, 23, 1),
163 TestCase(20, 9, 10, 2, -1)};
164 for (const auto& tc : test_cases) {
165 assert(math::ncr_modulo_p::NCRModuloP(tc.size, tc.p).ncr(tc.n, tc.r) ==
166 tc.expected);
167 }
168
169 std::cout << "\n\nAll tests have successfully passed!\n";
170}
int64_t ncr(const int64_t &n, const int64_t &r) const
computes nCr % p
represents single example inputs and expected output of the function longest_common_string_length