биноминальной коэффициент (n, k)
рассчитывается по формуле:
(n, k) = n!/k!/(n - k)!
Для того, чтобы сделать эту работу для большого числа n
и k
по модулю m
заметить, что:
факториал числа по модулю m
можно вычислить поэтапно, в каждый шаг, взяв результат % m
. Однако это будет слишком медленным с n до 10^18. Итак, есть faster methods, где сложность ограничена модулем, и вы можете использовать некоторые из них.
Разделение (a/b) mod m
равно (a * b^-1) mod m
, где b^-1
является обратным по модулю b
m
(то есть, (b * b^-1 = 1) mod m
).
Это означает, что:
(n, k) mod m = (n! * (k!)^-1 * ((n - k)!)^-1) mod m
Обратный ряд можно эффективно найти с помощью Extended Euclidean algorithm. Предполагая, что вы определили факториал, остальная часть алгоритма проста, просто следите за целыми переполнениями при умножении. Вот код ссылки, который работает до n=10^9
. Для обработки для больших чисел факториал вычисления должны быть заменены на более эффективный алгоритм и код должен быть слегка адаптированы, чтобы избежать целочисленные переполнения, но основная идея останется той же:
#define MOD 1000000007
// Extended Euclidean algorithm
int xGCD(int a, int b, int &x, int &y) {
if (b == 0) {
x = 1;
y = 0;
return a;
}
int x1, y1, gcd = xGCD(b, a % b, x1, y1);
x = y1;
y = x1 - (long long)(a/b) * y1;
return gcd;
}
// factorial of n modulo MOD
int modfact(int n) {
int result = 1;
while (n > 1) {
result = (long long)result * n % MOD;
n -= 1;
}
return result;
}
// multiply a and b modulo MOD
int modmult(int a, int b) {
return (long long)a * b % MOD;
}
// inverse of a modulo MOD
int inverse(int a) {
int x, y;
xGCD(a, MOD, x, y);
return x;
}
// binomial coefficient nCk modulo MOD
int bc(int n, int k)
{
return modmult(modmult(modfact(n), inverse(modfact(k))), inverse(modfact(n - k)));
}
Используйте обратный модуль. – vish4071