Added all functions inside a class + added more asserts

This commit is contained in:
KaustubhDamania
2020-10-22 12:06:10 +05:30
parent e44b7305ce
commit f6df24a589

View File

@@ -8,13 +8,35 @@
#include <iostream> #include <iostream>
#include <vector> #include <vector>
/** Finds the value of x, y such that a*x + b*y = gcd(a,b)
/** Class which contains all methods required for calculating nCr mod p
*
*/
class NCRModuloP {
private:
std::vector<int64_t> fac;
int64_t p;
public:
/** Constructor which precomputes the values of n! % mod from n=0 to size
* and stores them in vector 'fac'
* @params[in] the numbers 'size', 'mod'
*/
NCRModuloP(int64_t size, int64_t mod){
p = mod;
fac = std::vector<int64_t>(size);
fac[0] = 1;
for (int i = 1; i <= size; i++) {
fac[i] = (fac[i - 1] * i) % p;
}
}
/** Finds the value of x, y such that a*x + b*y = gcd(a,b)
* *
* @params[in] the numbers 'a', 'b' and address of 'x' and 'y' from above * @params[in] the numbers 'a', 'b' and address of 'x' and 'y' from above
* equation * equation
* @returns the gcd of a and b * @returns the gcd of a and b
*/ */
int64_t gcdExtended(int64_t a, int64_t b, int64_t *x, int64_t *y) { int64_t gcdExtended(int64_t a, int64_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;
@@ -26,14 +48,14 @@ int64_t gcdExtended(int64_t a, int64_t b, int64_t *x, int64_t *y) {
*x = y1 - (b / a) * x1; *x = y1 - (b / a) * x1;
*y = x1; *y = x1;
return gcd; return gcd;
} }
/** Find modular inverse of a with m i.e. a number x such that (a*x)%m = 1 /** Find modular inverse of a with m i.e. a number x such that (a*x)%m = 1
* *
* @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(int64_t a, int64_t m) { int64_t modInverse(int64_t a, int64_t m) {
int64_t x = 0, y = 0; int64_t x = 0, y = 0;
int64_t g = gcdExtended(a, m, &x, &y); int64_t g = gcdExtended(a, m, &x, &y);
if (g != 1) { // modular inverse doesn't exist if (g != 1) { // modular inverse doesn't exist
@@ -43,16 +65,14 @@ int64_t modInverse(int64_t a, int64_t m) {
int64_t res = (x % m + m) % m; int64_t res = (x % m + m) % m;
return res; return res;
} }
} }
std::vector<int64_t> fac; /** Find nCr % p
/** Find nCr % p
* *
* @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(int64_t n, int64_t r, int64_t p) { int64_t ncr(int64_t n, int64_t r, int64_t p) {
// Base cases // Base cases
if (r > n) { if (r > n) {
return 0; return 0;
@@ -73,8 +93,19 @@ int64_t ncr(int64_t n, int64_t r, int64_t p) {
return -1; return -1;
} }
return (fac[n] * denominator) % p; return (fac[n] * denominator) % p;
}
};
void tests(NCRModuloP ncrObj) {
// (52323 C 26161) % (1e9 + 7) = 224944353
assert(ncrObj.ncr(52323, 26161, 1000000007) == 224944353);
// 6 C 2 = 30, 30%5 = 0
assert(ncrObj.ncr(6,2,5) == 0);
// 7C3 = 35, 35 % 29 = 8
assert(ncrObj.ncr(7,3,29) == 6);
} }
/** /**
* @brief Main function * @brief Main function
* @returns 0 on exit * @returns 0 on exit
@@ -82,19 +113,12 @@ int64_t ncr(int64_t n, int64_t r, int64_t p) {
int main() { int main() {
// populate the fac array // populate the fac array
const int64_t size = 1e6 + 1; const int64_t size = 1e6 + 1;
fac = std::vector<int64_t>(size);
fac[0] = 1;
const int64_t p = 1e9 + 7; const int64_t p = 1e9 + 7;
for (int i = 1; i <= size; i++) { NCRModuloP ncrObj = NCRModuloP(size, p);
fac[i] = (fac[i - 1] * i) % 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 << " = " << ncr(6, i, p) << "\n"; std::cout << 6 << "C" << i << " = " << ncrObj.ncr(6, i, p) << "\n";
} }
tests(ncrObj);
// (52323 C 26161) % (1e9 + 7) = 224944353 std::cout << "Assertions passed\n";
assert(ncr(52323, 26161, p) == 224944353);
std::cout << "Assertion passed, (52323 C 26161) % (1e9 + 7) = 224944353\n";
} }