Add extra namespace + add const& in function arguments

This commit is contained in:
KaustubhDamania
2020-11-13 23:00:20 +05:30
parent 8e9803da1e
commit 8111f881e4

View File

@@ -1,10 +1,11 @@
/** /**
* @file * @file
* @brief This program aims at calculating nCr modulo p * @brief This program aims at calculating nCr modulo p. To know more about it,
* visit https://cp-algorithms.com/combinatorics/binomial-coefficients.html
* @details nCr is defined as n! / (r! * (n-r)!) where n! represents factorial * @details 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 * of n. In many cases, the value of nCr is too large to fit in a 64 bit integer.
* integer. Hence, in competitive programming, there are many problems or * Hence, in competitive programming, there are many problems or subproblems
* subproblems to compute nCr modulo p where p is a given number. * to compute nCr modulo p where p is a given number.
* @author [Kaustubh Damania](https://github.com/KaustubhDamania) * @author [Kaustubh Damania](https://github.com/KaustubhDamania)
*/ */
@@ -12,25 +13,30 @@
#include <iostream> /// for io operations #include <iostream> /// for io operations
#include <vector> /// for std::vector #include <vector> /// for std::vector
/** /**
* @namespace math * @namespace math
* @brief Mathematical algorithms * @brief Mathematical algorithms
*/ */
namespace math { namespace math {
/**
* @namespace ncr_modulo_p
* @brief Functions for nCr modulo p implementation.
*/
namespace ncr_modulo_p {
/** /**
* @brief Class which contains all methods required for calculating nCr mod p * @brief Class which contains all methods required for calculating nCr mod p
*/ */
class NCRModuloP { class NCRModuloP {
private: private:
std::vector<uint64_t> fac; std::vector<uint64_t> fac{};
uint64_t p; uint64_t p = 0;
public: public:
/** Constructor which precomputes the values of n! % mod from n=0 to size /** Constructor which precomputes the values of n! % mod from n=0 to size
* and stores them in vector 'fac' * and stores them in vector 'fac'
* @params[in] the numbers 'size', 'mod' * @params[in] the numbers 'size', 'mod'
*/ */
NCRModuloP(uint64_t size, uint64_t mod) { NCRModuloP(const uint64_t& size, const uint64_t& mod){
p = mod; p = mod;
fac = std::vector<uint64_t>(size); fac = std::vector<uint64_t>(size);
fac[0] = 1; fac[0] = 1;
@@ -45,7 +51,7 @@ class NCRModuloP {
* equation * equation
* @returns the gcd of a and b * @returns the gcd of a and b
*/ */
uint64_t gcdExtended(uint64_t a, uint64_t b, int64_t *x, int64_t *y) { uint64_t gcdExtended(const uint64_t& a, const uint64_t& b, int64_t *x, int64_t *y) {
if (a == 0) { if (a == 0) {
*x = 0, *y = 1; *x = 0, *y = 1;
return b; return b;
@@ -64,12 +70,13 @@ class NCRModuloP {
* @params[in] the numbers 'a' and 'm' from above equation * @params[in] the numbers 'a' and 'm' from above equation
* @returns the modular inverse of a * @returns the modular inverse of a
*/ */
int64_t modInverse(uint64_t a, uint64_t m) { int64_t modInverse(const uint64_t& a, const uint64_t& m) {
int64_t x = 0, y = 0; int64_t x = 0, y = 0;
uint64_t g = gcdExtended(a, m, &x, &y); uint64_t g = gcdExtended(a, m, &x, &y);
if (g != 1) { // modular inverse doesn't exist if (g != 1) { // modular inverse doesn't exist
return -1; return -1;
} else { }
else {
int64_t res = ((x + m) % m); int64_t res = ((x + m) % m);
return res; return res;
} }
@@ -80,7 +87,7 @@ class NCRModuloP {
* @params[in] the numbers 'n', 'r' and 'p' * @params[in] the numbers 'n', 'r' and 'p'
* @returns the value nCr % p * @returns the value nCr % p
*/ */
int64_t ncr(uint64_t n, uint64_t r, uint64_t p) { int64_t ncr(const uint64_t& n, const uint64_t& r, const uint64_t& p) {
// Base cases // Base cases
if (r > n) { if (r > n) {
return 0; return 0;
@@ -103,6 +110,7 @@ class NCRModuloP {
return (fac[n] * denominator) % p; return (fac[n] * denominator) % p;
} }
}; };
} // namespace ncr_modulo_p
} // namespace math } // namespace math
/** /**
@@ -111,7 +119,7 @@ class NCRModuloP {
* ncr function * ncr function
* @returns void * @returns void
*/ */
void tests(math::NCRModuloP ncrObj) { static void tests(math::ncr_modulo_p::NCRModuloP ncrObj) {
// (52323 C 26161) % (1e9 + 7) = 224944353 // (52323 C 26161) % (1e9 + 7) = 224944353
assert(ncrObj.ncr(52323, 26161, 1000000007) == 224944353); assert(ncrObj.ncr(52323, 26161, 1000000007) == 224944353);
// 6 C 2 = 30, 30%5 = 0 // 6 C 2 = 30, 30%5 = 0
@@ -120,6 +128,7 @@ void tests(math::NCRModuloP ncrObj) {
assert(ncrObj.ncr(7,3,29) == 6); assert(ncrObj.ncr(7,3,29) == 6);
} }
/** /**
* @brief Main function * @brief Main function
* @returns 0 on exit * @returns 0 on exit
@@ -128,11 +137,12 @@ int main() {
// populate the fac array // populate the fac array
const uint64_t size = 1e6 + 1; const uint64_t size = 1e6 + 1;
const uint64_t p = 1e9 + 7; const uint64_t p = 1e9 + 7;
math::NCRModuloP ncrObj = math::NCRModuloP(size, p); math::ncr_modulo_p::NCRModuloP ncrObj = math::ncr_modulo_p::NCRModuloP(size, p);
// test 6Ci for i=0 to 7 // test 6Ci for i=0 to 7
for (int i = 0; i <= 7; i++) { for (int i = 0; i <= 7; i++) {
std::cout << 6 << "C" << i << " = " << ncrObj.ncr(6, i, p) << "\n"; std::cout << 6 << "C" << i << " = " << ncrObj.ncr(6, i, p) << "\n";
} }
tests(ncrObj); // execute the tests tests(ncrObj); // execute the tests
std::cout << "Assertions passed\n"; std::cout << "Assertions passed\n";
return 0;
} }