给定三个数字n,r和p,计算n C r mod p的值。这里p是大于n的质数。在此, n C r是二项式系数。
例子:
Input: n = 10, r = 2, p = 13
Output: 6
Explanation: 10C2 is 45 and 45 % 13 is 6.
Input: n = 6, r = 2, p = 13
Output: 2
在之前的文章中,我们讨论了以下方法。
计算n C r %p |设置1(简介和动态编程解决方案)
计算n C r %p |第二套(卢卡斯定理)
在这篇文章中,讨论了基于费马定理的解决方案。
背景:
费马小定理和模逆
费马小定理指出,如果p是素数,那么对于任何整数a,数字a p – a是p的整数倍。在模块化算术的表示法中,这表示为:
a p = a(模p)
例如,如果a = 2且p = 7,则2 7 = 128,而128 – 2 = 7×18是7的整数倍。
如果a不能被p整除,则Fermat的小定理等于a – 1 – 1是p的整数倍,即
一个p-1 = 1(mod p)
如果我们将双方都乘以-1 ,我们得到。
a p-2 = a -1 (mod p)
因此我们可以找到p-2的模逆。
计算方式:
We know the formula for nCr
nCr = fact(n) / (fact(r) x fact(n-r))
Here fact() means factorial.
nCr % p = (fac[n]* modIverse(fac[r]) % p *
modIverse(fac[n-r]) % p) % p;
Here modIverse() means modular inverse under
modulo p.
以下是上述算法的实现。在以下实现中,数组fac []用于存储所有计算出的阶乘值。
C++
// A modular inverse based solution to
// compute nCr % p
#include
using namespace std;
/* Iterative Function to calculate (x^y)%p
in O(log y) */
unsigned long long power(unsigned long long x,
int y, int p)
{
unsigned long long res = 1; // Initialize result
x = x % p; // Update x if it is more than or
// equal to p
while (y > 0)
{
// If y is odd, multiply x with result
if (y & 1)
res = (res * x) % p;
// y must be even now
y = y >> 1; // y = y/2
x = (x * x) % p;
}
return res;
}
// Returns n^(-1) mod p
unsigned long long modInverse(unsigned long long n,
int p)
{
return power(n, p - 2, p);
}
// Returns nCr % p using Fermat's little
// theorem.
unsigned long long nCrModPFermat(unsigned long long n,
int r, int p)
{
// If n
Java
// A modular inverse based solution to
// compute nCr %
import java.io.*;
class GFG {
/* Iterative Function to calculate
(x^y)%p in O(log y) */
static int power(int x, int y, int p)
{
// Initialize result
int res = 1;
// Update x if it is more than or
// equal to p
x = x % p;
while (y > 0) {
// If y is odd, multiply x
// with result
if (y % 2 == 1)
res = (res * x) % p;
// y must be even now
y = y >> 1; // y = y/2
x = (x * x) % p;
}
return res;
}
// Returns n^(-1) mod p
static int modInverse(int n, int p)
{
return power(n, p - 2, p);
}
// Returns nCr % p using Fermat's
// little theorem.
static int nCrModPFermat(int n, int r,
int p)
{
if (n
Python3
# Python3 function to
# calculate nCr % p
def ncr(n, r, p):
# initialize numerator
# and denominator
num = den = 1
for i in range(r):
num = (num * (n - i)) % p
den = (den * (i + 1)) % p
return (num * pow(den,
p - 2, p)) % p
# p must be a prime
# greater than n
n, r, p = 10, 11, 13
print("Value of nCr % p is",
ncr(n, r, p))
C#
// A modular inverse based solution to
// compute nCr % p
using System;
class GFG {
/* Iterative Function to calculate
(x^y)%p in O(log y) */
static int power(int x, int y, int p)
{
// Initialize result
int res = 1;
// Update x if it is more than or
// equal to p
x = x % p;
while (y > 0) {
// If y is odd, multiply x
// with result
if (y % 2 == 1)
res = (res * x) % p;
// y must be even now
y = y >> 1; // y = y/2
x = (x * x) % p;
}
return res;
}
// Returns n^(-1) mod p
static int modInverse(int n, int p)
{
return power(n, p - 2, p);
}
// Returns nCr % p using Fermat's
// little theorem.
static int nCrModPFermat(int n, int r,
int p)
{
if (n
PHP
0)
{
// If y is odd,
// multiply x
// with result
if ($y & 1)
$res = ($res * $x) % $p;
// y must be
// even now
// y = y/2
$y = $y >> 1;
$x = ($x * $x) % $p;
}
return $res;
}
// Returns n^(-1) mod p
function modInverse($n, $p)
{
return power($n, $p - 2, $p);
}
// Returns nCr % p using
// Fermat's little
// theorem.
function nCrModPFermat($n, $r, $p)
{
if ($n<$r)
return 0;
// Base case
if ($r==0)
return 1;
// Fill factorial array so that we
// can find all factorial of r, n
// and n-r
//$fac[$n+1];
$fac[0] = 1;
for ($i = 1; $i <= $n; $i++)
$fac[$i] = $fac[$i - 1] *
$i % $p;
return ($fac[$n] * modInverse($fac[$r], $p) % $p *
modInverse($fac[$n - $r], $p) % $p) % $p;
}
// Driver Code
// p must be a prime
// greater than n.
$n = 10;
$r = 2;
$p = 13;
echo "Value of nCr % p is ",
nCrModPFermat($n, $r, $p);
// This code is contributed by Ajit.
?>
输出:
Value of nCr % p is 6