TheAlgorithms/C++
1.0.0
All the algorithms implemented in C++
Toggle main menu visibility
Loading...
Searching...
No Matches
ncr_modulo_p.cpp
Go to the documentation of this file.
1
11
12
#include <cassert>
13
#include <iostream>
14
#include <vector>
15
20
namespace
math
{
27
namespace
ncr_modulo_p
{
28
34
namespace
utils
{
44
int64_t
gcdExtended
(
const
int64_t& a,
const
int64_t& b, int64_t& x,
45
int64_t& y) {
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
}
59
66
int64_t
modInverse
(
const
int64_t& a,
const
int64_t& m) {
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
}
75
}
// namespace utils
79
class
NCRModuloP
{
80
private
:
81
const
int64_t p = 0;
82
const
std::vector<int64_t>
83
fac
;
84
92
static
std::vector<int64_t>
computeFactorialsMod
(
const
int64_t& max_arg_val,
93
const
int64_t& mod) {
94
auto
res = std::vector<int64_t>(max_arg_val + 1);
95
res[0] = 1;
96
for
(int64_t i = 1; i <= max_arg_val; i++) {
97
res[i] = (res[i - 1] * i) % mod;
98
}
99
return
res;
100
}
101
102
public
:
107
NCRModuloP
(
const
int64_t& size,
const
int64_t& p)
108
: p(p),
fac
(
computeFactorialsMod
(size, p)) {}
109
116
int64_t
ncr
(
const
int64_t& n,
const
int64_t& r)
const
{
117
// Base cases
118
if
(r > n) {
119
return
0;
120
}
121
if
(r == 1) {
122
return
n % p;
123
}
124
if
(r == 0 || r == n) {
125
return
1;
126
}
127
// fac is a global array with fac[r] = (r! % p)
128
const
auto
denominator = (
fac
[r] *
fac
[n - r]) % p;
129
const
auto
denominator_inv =
utils::modInverse
(denominator, p);
130
if
(denominator_inv < 0) {
// modular inverse doesn't exist
131
return
-1;
132
}
133
return
(
fac
[n] * denominator_inv) % p;
134
}
135
};
136
}
// namespace ncr_modulo_p
137
}
// namespace math
138
142
static
void
tests
() {
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
}
171
175
void
example
() {
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
}
190
191
int
main
() {
192
tests
();
193
example
();
194
return
0;
195
}
math::ncr_modulo_p::NCRModuloP
Class which contains all methods required for calculating nCr mod p.
Definition
ncr_modulo_p.cpp:79
math::ncr_modulo_p::NCRModuloP::ncr
int64_t ncr(const int64_t &n, const int64_t &r) const
computes nCr % p
Definition
ncr_modulo_p.cpp:116
math::ncr_modulo_p::NCRModuloP::fac
const std::vector< int64_t > fac
the p from (nCr % p)
Definition
ncr_modulo_p.cpp:83
math::ncr_modulo_p::NCRModuloP::NCRModuloP
NCRModuloP(const int64_t &size, const int64_t &p)
constructs an NCRModuloP object allowing to compute (nCr)p for inputs from 0 to size
Definition
ncr_modulo_p.cpp:107
math::ncr_modulo_p::NCRModuloP::computeFactorialsMod
static std::vector< int64_t > computeFactorialsMod(const int64_t &max_arg_val, const int64_t &mod)
stores precomputed factorial(i) % p value
Definition
ncr_modulo_p.cpp:92
gcd
int gcd(int num1, int num2)
Definition
gcd_iterative_euclidean.cpp:15
main
int main()
Main function.
Definition
generate_parentheses.cpp:110
math
for assert
ncr_modulo_p
Functions for nCr modulo p implementation.
tests
Testcases to check Union of Two Arrays.
utils
this namespace contains the definitions of the functions called from the class math::ncr_modulo_p::NC...
math::ncr_modulo_p::utils::modInverse
int64_t modInverse(const int64_t &a, const int64_t &m)
Definition
ncr_modulo_p.cpp:66
math::ncr_modulo_p::utils::gcdExtended
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)
Definition
ncr_modulo_p.cpp:44
example
void example()
example showing the usage of the math::ncr_modulo_p::NCRModuloP class
Definition
ncr_modulo_p.cpp:175
TestCase
represents single example inputs and expected output of the function longest_common_string_length
Definition
longest_common_string.cpp:54
math
ncr_modulo_p.cpp
Generated by
1.18.0