以下是二项式系数的常见定义。
A binomial coefficient C(n, k) can be defined as the coefficient of x^k in the expansion of (1 + x)^n.
A binomial coefficient C(n, k) also gives the number of ways, disregarding order, that k objects can be chosen from among n objects more formally, the number of k-element subsets (or k-combinations) of a n-element set.
问题
编写一个函数,它接受两个参数 n 和 k,并返回二项式系数 C(n, k) 的值。例如,你的函数应该返回6对于n = 4且k = 2,并且应当对于n = 5且k = 2返回10。
1) 最优子结构
C(n, k) 的值可以使用以下二项式系数的标准公式递归计算。
C(n, k) = C(n-1, k-1) + C(n-1, k)
C(n, 0) = C(n, n) = 1
下面是一个简单的递归实现,它简单地遵循上面提到的递归结构。
C++
// A naive recursive C++ implementation
#include
using namespace std;
// Returns value of Binomial Coefficient C(n, k)
int binomialCoeff(int n, int k)
{
// Base Cases
if (k > n)
return 0;
if (k == 0 || k == n)
return 1;
// Recur
return binomialCoeff(n - 1, k - 1)
+ binomialCoeff(n - 1, k);
}
/* Driver code*/
int main()
{
int n = 5, k = 2;
cout << "Value of C(" << n << ", " << k << ") is "
<< binomialCoeff(n, k);
return 0;
}
// This is code is contributed by rathbhupendra
C
// A Naive Recursive Implementation
#include
// Returns value of Binomial Coefficient C(n, k)
int binomialCoeff(int n, int k)
{
// Base Cases
if (k > n)
return 0;
if (k == 0 || k == n)
return 1;
// Recur
return binomialCoeff(n - 1, k - 1)
+ binomialCoeff(n - 1, k);
}
/* Driver program to test above function*/
int main()
{
int n = 5, k = 2;
printf("Value of C(%d, %d) is %d ", n, k,
binomialCoeff(n, k));
return 0;
}
Java
// JAVA Code for Dynamic Programming |
// Set 9 (Binomial Coefficient)
import java.util.*;
class GFG {
// Returns value of Binomial
// Coefficient C(n, k)
static int binomialCoeff(int n, int k)
{
// Base Cases
if (k > n)
return 0;
if (k == 0 || k == n)
return 1;
// Recur
return binomialCoeff(n - 1, k - 1)
+ binomialCoeff(n - 1, k);
}
/* Driver program to test above function */
public static void main(String[] args)
{
int n = 5, k = 2;
System.out.printf("Value of C(%d, %d) is %d ", n, k,
binomialCoeff(n, k));
}
}
// This code is contributed by Arnav Kr. Mandal.
Python
# A naive recursive Python implementation
def binomialCoeff(n, k):
if k > n:
return 0
if k == 0 or k == n:
return 1
# Recursive Call
return binomialCoeff(n-1, k-1) + binomialCoeff(n-1, k)
# Driver Program to test ht above function
n = 5
k = 2
print "Value of C(%d,%d) is (%d)" % (n, k,
binomialCoeff(n, k))
# This code is contributed by Nikhil Kumar Singh (nickzuck_007)
C#
// C# Code for Dynamic Programming |
// Set 9 (Binomial Coefficient)
using System;
class GFG {
// Returns value of Binomial
// Coefficient C(n, k)
static int binomialCoeff(int n, int k)
{
// Base Cases
if (k > n)
return 0;
if (k == 0 || k == n)
return 1;
// Recur
return binomialCoeff(n - 1, k - 1)
+ binomialCoeff(n - 1, k);
}
/* Driver program to test above function */
public static void Main()
{
int n = 5, k = 2;
Console.Write("Value of C(" + n + "," + k + ") is "
+ binomialCoeff(n, k));
}
}
// This code is contributed by Sam007.
PHP
$n)
return 0;
if ($k==0 || $k==$n)
return 1;
// Recur
return binomialCoeff($n - 1, $k - 1) +
binomialCoeff($n - 1, $k);
}
// Driver Code
$n = 5;
$k = 2;
echo "Value of C","(",$n ,$k,") is "
, binomialCoeff($n, $k);
// This code is contributed by aj_36
?>
Javascript
C++
// A Dynamic Programming based solution that uses
// table C[][] to calculate the Binomial Coefficient
#include
using namespace std;
// Prototype of a utility function that
// returns minimum of two integers
int min(int a, int b);
// Returns value of Binomial Coefficient C(n, k)
int binomialCoeff(int n, int k)
{
int C[n + 1][k + 1];
int i, j;
// Calculate value of Binomial Coefficient
// in bottom up manner
for (i = 0; i <= n; i++) {
for (j = 0; j <= min(i, k); j++) {
// Base Cases
if (j == 0 || j == i)
C[i][j] = 1;
// Calculate value using previously
// stored values
else
C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
}
}
return C[n][k];
}
// A utility function to return
// minimum of two integers
int min(int a, int b) { return (a < b) ? a : b; }
// Driver Code
int main()
{
int n = 5, k = 2;
cout << "Value of C[" << n << "][" << k << "] is "
<< binomialCoeff(n, k);
}
// This code is contributed by Shivi_Aggarwal
C
// A Dynamic Programming based solution
// that uses table C[][] to
// calculate the Binomial Coefficient
#include
// Prototype of a utility function that
// returns minimum of two integers
int min(int a, int b);
// Returns value of Binomial Coefficient C(n, k)
int binomialCoeff(int n, int k)
{
int C[n + 1][k + 1];
int i, j;
// Calculate value of Binomial Coefficient
// in bottom up manner
for (i = 0; i <= n; i++) {
for (j = 0; j <= min(i, k); j++) {
// Base Cases
if (j == 0 || j == i)
C[i][j] = 1;
// Calculate value using
// previously stored values
else
C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
}
}
return C[n][k];
}
// A utility function to return
// minimum of two integers
int min(int a, int b) { return (a < b) ? a : b; }
/* Drier program to test above function*/
int main()
{
int n = 5, k = 2;
printf("Value of C(%d, %d) is %d ", n, k,
binomialCoeff(n, k));
return 0;
}
Java
// A Dynamic Programming based
// solution that uses table C[][] to
// calculate the Binomial Coefficient
class BinomialCoefficient {
// Returns value of Binomial
// Coefficient C(n, k)
static int binomialCoeff(int n, int k)
{
int C[][] = new int[n + 1][k + 1];
int i, j;
// Calculate value of Binomial
// Coefficient in bottom up manner
for (i = 0; i <= n; i++) {
for (j = 0; j <= min(i, k); j++) {
// Base Cases
if (j == 0 || j == i)
C[i][j] = 1;
// Calculate value using
// previously stored values
else
C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
}
}
return C[n][k];
}
// A utility function to return
// minimum of two integers
static int min(int a, int b) { return (a < b) ? a : b; }
/* Driver program to test above function*/
public static void main(String args[])
{
int n = 5, k = 2;
System.out.println("Value of C(" + n + "," + k
+ ") is " + binomialCoeff(n, k));
}
}
/*This code is contributed by Rajat Mishra*/
Python
# A Dynamic Programming based Python
# Program that uses table C[][]
# to calculate the Binomial Coefficient
# Returns value of Binomial Coefficient C(n, k)
def binomialCoef(n, k):
C = [[0 for x in range(k+1)] for x in range(n+1)]
# Calculate value of Binomial
# Coefficient in bottom up manner
for i in range(n+1):
for j in range(min(i, k)+1):
# Base Cases
if j == 0 or j == i:
C[i][j] = 1
# Calculate value using
# previously stored values
else:
C[i][j] = C[i-1][j-1] + C[i-1][j]
return C[n][k]
# Driver program to test above function
n = 5
k = 2
print("Value of C[" + str(n) + "][" + str(k) + "] is "
+ str(binomialCoef(n, k)))
# This code is contributed by Bhavya Jain
C#
// A Dynamic Programming based solution that
// uses table C[][] to calculate the Binomial
// Coefficient
using System;
class GFG {
// Returns value of Binomial Coefficient
// C(n, k)
static int binomialCoeff(int n, int k)
{
int[, ] C = new int[n + 1, k + 1];
int i, j;
// Calculate value of Binomial
// Coefficient in bottom up manner
for (i = 0; i <= n; i++) {
for (j = 0; j <= Math.Min(i, k); j++) {
// Base Cases
if (j == 0 || j == i)
C[i, j] = 1;
// Calculate value using previously
// stored values
else
C[i, j] = C[i - 1, j - 1] + C[i - 1, j];
}
}
return C[n, k];
}
// A utility function to return minimum
// of two integers
static int min(int a, int b) { return (a < b) ? a : b; }
/* Driver program to test above function*/
public static void Main()
{
int n = 5, k = 2;
Console.WriteLine("Value of C(" + n + "," + k
+ ") is " + binomialCoeff(n, k));
}
}
// This code is contributed by anuj_67.
PHP
Javascript
C++
// C++ program for space optimized Dynamic Programming
// Solution of Binomial Coefficient
#include
using namespace std;
int binomialCoeff(int n, int k)
{
int C[k + 1];
memset(C, 0, sizeof(C));
C[0] = 1; // nC0 is 1
for (int i = 1; i <= n; i++) {
// Compute next row of pascal triangle using
// the previous row
for (int j = min(i, k); j > 0; j--)
C[j] = C[j] + C[j - 1];
}
return C[k];
}
/* Driver code*/
int main()
{
int n = 5, k = 2;
printf("Value of C(%d, %d) is %d ", n, k,
binomialCoeff(n, k));
return 0;
}
Java
// JAVA Code for Dynamic Programming |
// Set 9 (Binomial Coefficient)
import java.util.*;
class GFG {
static int binomialCoeff(int n, int k)
{
int C[] = new int[k + 1];
// nC0 is 1
C[0] = 1;
for (int i = 1; i <= n; i++) {
// Compute next row of pascal
// triangle using the previous row
for (int j = Math.min(i, k); j > 0; j--)
C[j] = C[j] + C[j - 1];
}
return C[k];
}
/* Driver code */
public static void main(String[] args)
{
int n = 5, k = 2;
System.out.printf("Value of C(%d, %d) is %d ", n, k,
binomialCoeff(n, k));
}
}
Python
# Python program for Optimized
# Dynamic Programming solution to
# Binomail Coefficient. This one
# uses the concept of pascal
# Triangle and less memory
def binomialCoeff(n, k):
# Declaring an empty array
C = [0 for i in xrange(k+1)]
C[0] = 1 # since nC0 is 1
for i in range(1, n+1):
# Compute next row of pascal triangle using
# the previous row
j = min(i, k)
while (j > 0):
C[j] = C[j] + C[j-1]
j -= 1
return C[k]
# Driver Code
n = 5
k = 2
print "Value of C(%d,%d) is %d" % (n, k, binomialCoeff(n, k))
# This code is contribtued by Nikhil Kumar Singh(nickzuck_007)
C#
// C# Code for Dynamic Programming |
// Set 9 (Binomial Coefficient)
using System;
class GFG {
static int binomialCoeff(int n, int k)
{
int[] C = new int[k + 1];
// nC0 is 1
C[0] = 1;
for (int i = 1; i <= n; i++) {
// Compute next row of pascal
// triangle using the previous
// row
for (int j = Math.Min(i, k); j > 0; j--)
C[j] = C[j] + C[j - 1];
}
return C[k];
}
/* Driver Code */
public static void Main()
{
int n = 5, k = 2;
Console.WriteLine("Value of C(" + n + " " + k
+ ") is " + binomialCoeff(n, k));
}
}
// This code is contribtued by anuj_67.
PHP
0; $j--)
$C[$j] = $C[$j] + $C[$j - 1];
}
return $C[$k];
}
// Driver Code
$n = 5; $k = 2;
echo "Value of C[$n, $k] is ".
binomialCoeff($n, $k);
// This code is contributed by mits.
?>
Javascript
C++
// A Dynamic Programming based
// solution that uses
// table dp[][] to calculate
// the Binomial Coefficient
// A naive recursive approach
// with table C++ implementation
#include
using namespace std;
// Returns value of Binomial Coefficient C(n, k)
int binomialCoeffUtil(int n, int k, int** dp)
{
// If value in lookup table then return
if (dp[n][k] != -1) //
return dp[n][k];
// store value in a table before return
if (k == 0) {
dp[n][k] = 1;
return dp[n][k];
}
// store value in table before return
if (k == n) {
dp[n][k] = 1;
return dp[n][k];
}
// save value in lookup table before return
dp[n][k] = binomialCoeffUtil(n - 1, k - 1, dp) +
binomialCoeffUtil(n - 1, k, dp);
return dp[n][k];
}
int binomialCoeff(int n, int k)
{
int** dp; // make a temporary lookup table
dp = new int*[n + 1];
// loop to create table dynamically
for (int i = 0; i < (n + 1); i++) {
dp[i] = new int[k + 1];
}
// nested loop to initialise the table with -1
for (int i = 0; i < (n + 1); i++) {
for (int j = 0; j < (k + 1); j++) {
dp[i][j] = -1;
}
}
return binomialCoeffUtil(n, k, dp);
}
/* Driver code*/
int main()
{
int n = 5, k = 2;
cout << "Value of C(" << n << ", " << k << ") is "
<< binomialCoeff(n, k) << endl;
return 0;
}
// This is code is contributed by MOHAMMAD MUDASSIR
Java
// A Dynamic Programming based
// solution that uses
// table dp[][] to calculate
// the Binomial Coefficient
// A naive recursive approach
// with table Java implementation
import java.util.*;
class GFG{
// Returns value of Binomial
// Coefficient C(n, k)
static int binomialCoeffUtil(int n, int k,
Vector []dp)
{
// If value in lookup table
// then return
if (dp[n].get(k) != -1)
return dp[n].get(k);
// store value in a table
// before return
if (k == 0)
{
dp[n].add(k, 1);
return dp[n].get(k);
}
// store value in table
// before return
if (k == n)
{
dp[n].add(k, 1);
return dp[n].get(k);
}
// save value in lookup table
// before return
dp[n].add(k, binomialCoeffUtil(n - 1,
k - 1, dp) +
binomialCoeffUtil(n - 1,
k, dp));
return dp[n].get(k);
}
static int binomialCoeff(int n, int k)
{
// Make a temporary lookup table
Vector []dp = new Vector[n+1];
// Loop to create table dynamically
for (int i = 0; i < (n + 1); i++)
{
dp[i] = new Vector();
for(int j = 0; j <= k; j++)
dp[i].add(-1);
}
return binomialCoeffUtil(n, k, dp);
}
// Driver code
public static void main(String[] args)
{
int n = 5, k = 2;
System.out.print("Value of C(" + n +
", " + k + ") is " +
binomialCoeff(n, k) + "\n");
}
}
// This code is contributed by Rajput-Ji
Python3
# A Dynamic Programming based solution
# that uses table dp[][] to calculate
# the Binomial Coefficient. A naive
# recursive approach with table
# Python3 implementation
# Returns value of Binomial
# Coefficient C(n, k)
def binomialCoeffUtil(n, k, dp):
# If value in lookup table then return
if dp[n][k] != -1:
return dp[n][k]
# Store value in a table before return
if k == 0:
dp[n][k] = 1
return dp[n][k]
# Store value in table before return
if k == n:
dp[n][k] = 1
return dp[n][k]
# Save value in lookup table before return
dp[n][k] = (binomialCoeffUtil(n - 1, k - 1, dp) +
binomialCoeffUtil(n - 1, k, dp))
return dp[n][k]
def binomialCoeff(n, k):
# Make a temporary lookup table
dp = [ [ -1 for y in range(k + 1) ]
for x in range(n + 1) ]
return binomialCoeffUtil(n, k, dp)
# Driver code
n = 5
k = 2
print("Value of C(" + str(n) +
", " + str(k) + ") is",
binomialCoeff(n, k))
# This is code is contributed by Prateek Gupta
C#
// C# program for the
// above approach
// A Dynamic Programming based
// solution that uses
// table [,]dp to calculate
// the Binomial Coefficient
// A naive recursive approach
// with table C# implementation
using System;
using System.Collections.Generic;
class GFG{
// Returns value of Binomial
// Coefficient C(n, k)
static int binomialCoeffUtil(int n, int k,
List []dp)
{
// If value in lookup table
// then return
if (dp[n][k] != -1)
return dp[n][k];
// store value in a table
// before return
if (k == 0)
{
dp[n][k] = 1;
return dp[n][k];
}
// store value in table
// before return
if (k == n)
{
dp[n][k] = 1;
return dp[n][k];
}
// save value in lookup table
// before return
dp[n][k] = binomialCoeffUtil(n - 1,
k - 1, dp) +
binomialCoeffUtil(n - 1,
k, dp);
return dp[n][k];
}
static int binomialCoeff(int n, int k)
{
// Make a temporary lookup table
List []dp = new List[n + 1];
// Loop to create table dynamically
for (int i = 0; i < (n + 1); i++)
{
dp[i] = new List();
for(int j = 0; j <= k; j++)
dp[i].Add(-1);
}
return binomialCoeffUtil(n, k, dp);
}
// Driver code
public static void Main(String[] args)
{
int n = 5, k = 2;
Console.Write("Value of C(" + n +
", " + k + ") is " +
binomialCoeff(n, k) + "\n");
}
}
// This code is contributed by 29AjayKumar
Javascript
Java
import java.util.*;
class GFG
{
static int gcd(int a, int b) // function to find gcd of two numbers in O(log(min(a,b)))
{
if(b==0) return a;
return gcd(b,a%b);
}
static int nCr(int n, int r)
{
if(r>n) // base case
return 0;
if(r>n-r) // C(n,r) = C(n,n-r) better time complexity for lesser r value
r = n-r;
int mod = 1000000007;
int[] arr = new int[r]; // array of elements from n-r+1 to n
for(int i=n-r+1; i<=n; i++)
{
arr[i+r-n-1] = i;
}
long ans = 1;
for(int k=1;k1
{
int j=0, i=k;
while(j1)
{
arr[j] /= x; // if gcd>1, divide both by gcd
i /= x;
}
if(i==1)
break; // if i becomes 1, no need to search arr
j += 1;
}
}
for(int i : arr) // single pass to multiply the numerator
ans = (ans*i)%mod;
return (int)ans;
}
// Driver code
public static void main(String[] args)
{
int n = 5, r = 2;
System.out.print("Value of C(" + n+ ", " + r+ ") is "
+nCr(n, r) +"\n");
}
}
// This code is contributed by Gautam Wadhwani
Python3
import math
class GFG:
def nCr(self, n, r):
def gcd(a,b): # function to find gcd of two numbers in O(log(min(a,b)))
if b==0: # base case
return a
return gcd(b,a%b)
if r>n:
return 0
if r>n-r: # C(n,r) = C(n,n-r) better time complexity for lesser r value
r = n-r
mod = 10**9 + 7
arr = list(range(n-r+1,n+1)) # array of elements from n-r+1 to n
ans = 1
for i in range(1,r+1): # for numbers from 1 to r find arr[j] such that gcd(i,arr[j])>1
j=0
while j1:
arr[j] //= x # if gcd>1, divide both by gcd
i //= x
if arr[j]==1: # if element becomes 1, its of no use anymore so delete from arr
del arr[j]
j -= 1
if i==1:
break # if i becomes 1, no need to search arr
j += 1
for i in arr: # single pass to multiply the numerator
ans = (ans*i)%mod
return ans
# Driver code
n = 5
k = 2
ob = GFG()
print("Value of C(" + str(n) +
", " + str(k) + ") is",
ob.nCr(n, k))
# This is code is contributed by Gautam Wadhwani
C#
using System;
class GFG{
// Function to find gcd of two numbers
// in O(log(min(a,b)))
static int gcd(int a, int b)
{
if (b == 0)
return a;
return gcd(b, a % b);
}
static int nCr(int n, int r)
{
// Base case
if (r > n)
return 0;
// C(n,r) = C(n,n-r) better time
// complexity for lesser r value
if (r > n - r)
r = n - r;
int mod = 1000000007;
// Array of elements from n-r+1 to n
int[] arr = new int[r];
for(int i = n - r + 1; i <= n; i++)
{
arr[i + r - n - 1] = i;
}
long ans = 1;
// For numbers from 1 to r find arr[j]
// such that gcd(i,arr[j])>1
for(int k = 1; k < r + 1; k++)
{
int j = 0, i = k;
while (j < arr.Length)
{
int x = gcd(i,arr[j]);
if (x > 1)
{
// If gcd>1, divide both by gcd
arr[j] /= x;
i /= x;
}
if (i == 1)
// If i becomes 1, no need
// to search arr
break;
j += 1;
}
}
// Single pass to multiply the numerator
foreach(int i in arr)
ans = (ans * i) % mod;
return (int)ans;
}
// Driver code
static public void Main()
{
int n = 5, r = 2;
Console.WriteLine("Value of C(" + n +
", " + r + ") is " +
nCr(n, r) + "\n");
}
}
// This code is contributed by rag2127
Java
import java.util.*;
class GFG {
// pow(base,exp,mod) is used to find
// (base^exp)%mod fast -> O(log(exp))
static long pow(long b, long exp, long mod)
{
long ret = 1;
while (exp > 0) {
if ((exp & 1) > 0)
ret = (ret * b) % mod;
b = (b * b) % mod;
exp >>= 1;
}
return ret;
}
static int nCr(int n, int r)
{
if (r > n) // base case
return 0;
// C(n,r) = C(n,n-r) Complexity for
// this code is lesser for lower n-r
if (n - r > r)
r = n - r;
// list to smallest prime factor
// of each number from 1 to n
int[] SPF = new int[n + 1];
// set smallest prime factor of each
// number as itself
for (int i = 1; i <= n; i++)
SPF[i] = i;
// set smallest prime factor of all
// even numbers as 2
for (int i = 4; i <= n; i += 2)
SPF[i] = 2;
for (int i = 3; i * i < n + 1; i += 2)
{
// Check if i is prime
if (SPF[i] == i)
{
// All multiples of i are
// composite (and divisible by
// i) so add i to their prime
// factorization getpow(j,i)
// times
for (int j = i * i; j < n + 1; j += i)
if (SPF[j] == j) {
SPF[j] = i;
}
}
}
// Hash Map to store power of
// each prime in C(n,r)
Map prime_pow
= new HashMap<>();
// For numerator count frequency of each prime factor
for (int i = r + 1; i < n + 1; i++)
{
int t = i;
// Recursive division to find
// prime factorization of i
while (t > 1)
{
prime_pow.put(SPF[t],
prime_pow.getOrDefault(SPF[t], 0) + 1);
t /= SPF[t];
}
}
// For denominator subtract the power of
// each prime factor
for (int i = 1; i < n - r + 1; i++)
{
int t = i;
// Recursive division to find
// prime factorization of i
while (t > 1)
{
prime_pow.put(SPF[t],
prime_pow.get(SPF[t]) - 1);
t /= SPF[t];
}
}
// long because mod is large and a%mod
// * b%mod can overflow int
long ans = 1, mod = 1000000007;
// use (a*b)%mod = (a%mod * b%mod)%mod
for (int i : prime_pow.keySet())
// pow(base,exp,mod) is used to
// find (base^exp)%mod fast
ans = (ans * pow(i, prime_pow.get(i), mod))
% mod;
return (int)ans;
}
// Driver code
public static void main(String[] args)
{
int n = 5, r = 2;
System.out.print("Value of C(" + n + ", " + r
+ ") is " + nCr(n, r) + "\n");
}
}
// This code is contributed by Gautam Wadhwani
Python3
# Python code for the above approach
import math
class GFG:
def nCr(self, n, r):
# Base case
if r > n:
return 0
# C(n,r) = C(n,n-r) Complexity for this
# code is lesser for lower n-r
if n - r > r:
r = n - r
# List to store smallest prime factor
# of every number from 1 to n
SPF = [i for i in range(n+1)]
for i in range(4, n+1, 2):
# set smallest prime factor of
# all even numbers as 2
SPF[i] = 2
for i in range(3, n+1, 2):
if i*i > n:
break
# Check if i is prime
if SPF[i] == i:
# All multiples of i are composite
# (and divisible by i) so add i to
# their prime factorization getpow(j,i) times
for j in range(i*i, n+1, i):
if SPF[j] == j:
# set smallest prime factor
# of j to i only if it is
# not previously set
SPF[j] = i
# dictionary to store power of each prime in C(n,r)
prime_pow = {}
# For numerator count frequency
# of each prime factor
for i in range(r+1, n+1):
t = i
# Recursive division to
# find prime factorization of i
while t > 1:
if not SPF[t] in prime_pow:
prime_pow[SPF[t]] = 1
else:
prime_pow[SPF[t]] += 1
t //= SPF[t]
# For denominator subtract the
# power of each prime factor
for i in range(1, n-r+1):
t = i
# Recursive division to
# find prime factorization of i
while t > 1:
prime_pow[SPF[t]] -= 1
t //= SPF[t]
ans = 1
mod = 10**9 + 7
# Use (a*b)%mod = (a%mod * b%mod)%mod
for i in prime_pow:
# pow(base,exp,mod) is used to
# find (base^exp)%mod fast
ans = (ans*pow(i, prime_pow[i], mod)) % mod
return ans
# Driver code
n = 5
k = 2
ob = GFG()
print("Value of C(" + str(n) +
", " + str(k) + ") is",
ob.nCr(n, k))
# This is code is contributed by Gautam Wadhwani
C++
// C++ program for the above approach
#include
using namespace std;
// Function to find binomial
// coefficient
int binomialCoeff(int n, int r)
{
if (r > n)
return 0;
long long int m = 1000000007;
long long int inv[r + 1] = { 0 };
inv[0] = 1;
if(r+1>=2)
inv[1] = 1;
// Getting the modular inversion
// for all the numbers
// from 2 to r with respect to m
// here m = 1000000007
for (int i = 2; i <= r; i++) {
inv[i] = m - (m / i) * inv[m % i] % m;
}
int ans = 1;
// for 1/(r!) part
for (int i = 2; i <= r; i++) {
ans = ((ans % m) * (inv[i] % m)) % m;
}
// for (n)*(n-1)*(n-2)*...*(n-r+1) part
for (int i = n; i >= (n - r + 1); i--) {
ans = ((ans % m) * (i % m)) % m;
}
return ans;
}
/* Driver code*/
int main()
{
int n = 5, r = 2;
cout << "Value of C(" << n << ", " << r << ") is "
<< binomialCoeff(n, r) << endl;
return 0;
}
Java
// JAVA program for the above approach
import java.util.*;
class GFG
{
// Function to find binomial
// coefficient
static int binomialCoeff(int n, int r)
{
if (r > n)
return 0;
long m = 1000000007;
long inv[] = new long[r + 1];
inv[0] = 1;
if(r+1>=2)
inv[1] = 1;
// Getting the modular inversion
// for all the numbers
// from 2 to r with respect to m
// here m = 1000000007
for (int i = 2; i <= r; i++) {
inv[i] = m - (m / i) * inv[(int) (m % i)] % m;
}
int ans = 1;
// for 1/(r!) part
for (int i = 2; i <= r; i++) {
ans = (int) (((ans % m) * (inv[i] % m)) % m);
}
// for (n)*(n-1)*(n-2)*...*(n-r+1) part
for (int i = n; i >= (n - r + 1); i--) {
ans = (int) (((ans % m) * (i % m)) % m);
}
return ans;
}
/* Driver code*/
public static void main(String[] args)
{
int n = 5, r = 2;
System.out.print("Value of C(" + n+ ", " + r+ ") is "
+binomialCoeff(n, r) +"\n");
}
}
// This code contributed by Rajput-Ji
Python3
# Python3 program for the above approach
# Function to find binomial
# coefficient
def binomialCoeff(n, r):
if (r > n):
return 0
m = 1000000007
inv = [0 for i in range(r + 1)]
inv[0] = 1;
if(r+1>=2)
inv[1] = 1;
# Getting the modular inversion
# for all the numbers
# from 2 to r with respect to m
# here m = 1000000007
for i in range(2, r + 1):
inv[i] = m - (m // i) * inv[m % i] % m
ans = 1
# for 1/(r!) part
for i in range(2, r + 1):
ans = ((ans % m) * (inv[i] % m)) % m
# for (n)*(n-1)*(n-2)*...*(n-r+1) part
for i in range(n, n - r, -1):
ans = ((ans % m) * (i % m)) % m
return ans
# Driver code
n = 5
r = 2
print("Value of C(" ,n , ", " , r ,
") is ",binomialCoeff(n, r))
# This code is contributed by rohan07
C#
// C# program for the above approach
using System;
public class GFG
{
// Function to find binomial
// coefficient
static int binomialCoeff(int n, int r)
{
if (r > n)
return 0;
long m = 1000000007;
long []inv = new long[r + 1];
inv[0] = 1;
if(r+1>=2)
inv[1] = 1;
// Getting the modular inversion
// for all the numbers
// from 2 to r with respect to m
// here m = 1000000007
for (int i = 2; i <= r; i++) {
inv[i] = m - (m / i) * inv[(int) (m % i)] % m;
}
int ans = 1;
// for 1/(r!) part
for (int i = 2; i <= r; i++) {
ans = (int) (((ans % m) * (inv[i] % m)) % m);
}
// for (n)*(n-1)*(n-2)*...*(n-r+1) part
for (int i = n; i >= (n - r + 1); i--) {
ans = (int) (((ans % m) * (i % m)) % m);
}
return ans;
}
/* Driver code*/
public static void Main(String[] args)
{
int n = 5, r = 2;
Console.Write("Value of C(" + n+ ", " + r+ ") is "
+binomialCoeff(n, r) +"\n");
}
}
// This code is contributed by 29AjayKumar
Javascript
Value of C(5, 2) is 10
2) 重叠子问题
需要注意的是,上述函数一次又一次地计算相同的子问题。对于 n = 5 和 k = 2,请参见以下递归树。函数C(3, 1) 被调用两次。对于较大的 n 值,将有许多常见的子问题。
由于再次调用相同的子问题,该问题具有重叠子问题的性质。所以二项式系数问题具有动态规划问题的两个属性(见this和this)。与其他典型的动态规划 (DP) 问题一样,可以通过以自底向上的方式构造临时二维数组 C[][] 来避免对相同子问题的重新计算。以下是基于动态规划的实现。
C++
// A Dynamic Programming based solution that uses
// table C[][] to calculate the Binomial Coefficient
#include
using namespace std;
// Prototype of a utility function that
// returns minimum of two integers
int min(int a, int b);
// Returns value of Binomial Coefficient C(n, k)
int binomialCoeff(int n, int k)
{
int C[n + 1][k + 1];
int i, j;
// Calculate value of Binomial Coefficient
// in bottom up manner
for (i = 0; i <= n; i++) {
for (j = 0; j <= min(i, k); j++) {
// Base Cases
if (j == 0 || j == i)
C[i][j] = 1;
// Calculate value using previously
// stored values
else
C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
}
}
return C[n][k];
}
// A utility function to return
// minimum of two integers
int min(int a, int b) { return (a < b) ? a : b; }
// Driver Code
int main()
{
int n = 5, k = 2;
cout << "Value of C[" << n << "][" << k << "] is "
<< binomialCoeff(n, k);
}
// This code is contributed by Shivi_Aggarwal
C
// A Dynamic Programming based solution
// that uses table C[][] to
// calculate the Binomial Coefficient
#include
// Prototype of a utility function that
// returns minimum of two integers
int min(int a, int b);
// Returns value of Binomial Coefficient C(n, k)
int binomialCoeff(int n, int k)
{
int C[n + 1][k + 1];
int i, j;
// Calculate value of Binomial Coefficient
// in bottom up manner
for (i = 0; i <= n; i++) {
for (j = 0; j <= min(i, k); j++) {
// Base Cases
if (j == 0 || j == i)
C[i][j] = 1;
// Calculate value using
// previously stored values
else
C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
}
}
return C[n][k];
}
// A utility function to return
// minimum of two integers
int min(int a, int b) { return (a < b) ? a : b; }
/* Drier program to test above function*/
int main()
{
int n = 5, k = 2;
printf("Value of C(%d, %d) is %d ", n, k,
binomialCoeff(n, k));
return 0;
}
Java
// A Dynamic Programming based
// solution that uses table C[][] to
// calculate the Binomial Coefficient
class BinomialCoefficient {
// Returns value of Binomial
// Coefficient C(n, k)
static int binomialCoeff(int n, int k)
{
int C[][] = new int[n + 1][k + 1];
int i, j;
// Calculate value of Binomial
// Coefficient in bottom up manner
for (i = 0; i <= n; i++) {
for (j = 0; j <= min(i, k); j++) {
// Base Cases
if (j == 0 || j == i)
C[i][j] = 1;
// Calculate value using
// previously stored values
else
C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
}
}
return C[n][k];
}
// A utility function to return
// minimum of two integers
static int min(int a, int b) { return (a < b) ? a : b; }
/* Driver program to test above function*/
public static void main(String args[])
{
int n = 5, k = 2;
System.out.println("Value of C(" + n + "," + k
+ ") is " + binomialCoeff(n, k));
}
}
/*This code is contributed by Rajat Mishra*/
Python
# A Dynamic Programming based Python
# Program that uses table C[][]
# to calculate the Binomial Coefficient
# Returns value of Binomial Coefficient C(n, k)
def binomialCoef(n, k):
C = [[0 for x in range(k+1)] for x in range(n+1)]
# Calculate value of Binomial
# Coefficient in bottom up manner
for i in range(n+1):
for j in range(min(i, k)+1):
# Base Cases
if j == 0 or j == i:
C[i][j] = 1
# Calculate value using
# previously stored values
else:
C[i][j] = C[i-1][j-1] + C[i-1][j]
return C[n][k]
# Driver program to test above function
n = 5
k = 2
print("Value of C[" + str(n) + "][" + str(k) + "] is "
+ str(binomialCoef(n, k)))
# This code is contributed by Bhavya Jain
C#
// A Dynamic Programming based solution that
// uses table C[][] to calculate the Binomial
// Coefficient
using System;
class GFG {
// Returns value of Binomial Coefficient
// C(n, k)
static int binomialCoeff(int n, int k)
{
int[, ] C = new int[n + 1, k + 1];
int i, j;
// Calculate value of Binomial
// Coefficient in bottom up manner
for (i = 0; i <= n; i++) {
for (j = 0; j <= Math.Min(i, k); j++) {
// Base Cases
if (j == 0 || j == i)
C[i, j] = 1;
// Calculate value using previously
// stored values
else
C[i, j] = C[i - 1, j - 1] + C[i - 1, j];
}
}
return C[n, k];
}
// A utility function to return minimum
// of two integers
static int min(int a, int b) { return (a < b) ? a : b; }
/* Driver program to test above function*/
public static void Main()
{
int n = 5, k = 2;
Console.WriteLine("Value of C(" + n + "," + k
+ ") is " + binomialCoeff(n, k));
}
}
// This code is contributed by anuj_67.
PHP
Javascript
Value of C[5][2] is 10
时间复杂度: O(n*k)
辅助空间: O(n*k)
以下是上述代码的空间优化版本。以下代码仅使用 O(k)。感谢AK提出这个方法。
C++
// C++ program for space optimized Dynamic Programming
// Solution of Binomial Coefficient
#include
using namespace std;
int binomialCoeff(int n, int k)
{
int C[k + 1];
memset(C, 0, sizeof(C));
C[0] = 1; // nC0 is 1
for (int i = 1; i <= n; i++) {
// Compute next row of pascal triangle using
// the previous row
for (int j = min(i, k); j > 0; j--)
C[j] = C[j] + C[j - 1];
}
return C[k];
}
/* Driver code*/
int main()
{
int n = 5, k = 2;
printf("Value of C(%d, %d) is %d ", n, k,
binomialCoeff(n, k));
return 0;
}
Java
// JAVA Code for Dynamic Programming |
// Set 9 (Binomial Coefficient)
import java.util.*;
class GFG {
static int binomialCoeff(int n, int k)
{
int C[] = new int[k + 1];
// nC0 is 1
C[0] = 1;
for (int i = 1; i <= n; i++) {
// Compute next row of pascal
// triangle using the previous row
for (int j = Math.min(i, k); j > 0; j--)
C[j] = C[j] + C[j - 1];
}
return C[k];
}
/* Driver code */
public static void main(String[] args)
{
int n = 5, k = 2;
System.out.printf("Value of C(%d, %d) is %d ", n, k,
binomialCoeff(n, k));
}
}
Python
# Python program for Optimized
# Dynamic Programming solution to
# Binomail Coefficient. This one
# uses the concept of pascal
# Triangle and less memory
def binomialCoeff(n, k):
# Declaring an empty array
C = [0 for i in xrange(k+1)]
C[0] = 1 # since nC0 is 1
for i in range(1, n+1):
# Compute next row of pascal triangle using
# the previous row
j = min(i, k)
while (j > 0):
C[j] = C[j] + C[j-1]
j -= 1
return C[k]
# Driver Code
n = 5
k = 2
print "Value of C(%d,%d) is %d" % (n, k, binomialCoeff(n, k))
# This code is contribtued by Nikhil Kumar Singh(nickzuck_007)
C#
// C# Code for Dynamic Programming |
// Set 9 (Binomial Coefficient)
using System;
class GFG {
static int binomialCoeff(int n, int k)
{
int[] C = new int[k + 1];
// nC0 is 1
C[0] = 1;
for (int i = 1; i <= n; i++) {
// Compute next row of pascal
// triangle using the previous
// row
for (int j = Math.Min(i, k); j > 0; j--)
C[j] = C[j] + C[j - 1];
}
return C[k];
}
/* Driver Code */
public static void Main()
{
int n = 5, k = 2;
Console.WriteLine("Value of C(" + n + " " + k
+ ") is " + binomialCoeff(n, k));
}
}
// This code is contribtued by anuj_67.
PHP
0; $j--)
$C[$j] = $C[$j] + $C[$j - 1];
}
return $C[$k];
}
// Driver Code
$n = 5; $k = 2;
echo "Value of C[$n, $k] is ".
binomialCoeff($n, $k);
// This code is contributed by mits.
?>
Javascript
Value of C(5, 2) is 10
时间复杂度: O(n*k)
辅助空间: O(k)
解释:
1==========>> n = 0, C(0,0) = 1
1–1========>> n = 1, C(1,0) = 1, C(1,1) = 1
1–2–1======>> n = 2, C(2,0) = 1, C(2,1) = 2, C(2,2) = 1
1–3–3–1====>> n = 3, C(3,0) = 1, C(3,1) = 3, C(3,2) = 3, C(3,3) =1
1–4–6–4–1==>> n = 4, C(4,0) = 1, C(4,1) = 4, C(4,2) = 6, C(4,3) =4,C(4,4)=1
所以这里我的每个循环,使用第 (i-1) 行构建第 i 行的帕斯卡三角形
在任何时候,数组 C 的每个元素都会有一些值(零或更多),并且在下一次迭代中,这些元素的值来自前一次迭代。
在声明中,
C[j] = C[j] + C[j-1]
右侧代表来自前一次迭代的值(帕斯卡三角形的一行取决于前一行)。左侧表示将通过该语句获得的当前迭代的值。
Let's say we want to calculate C(4, 3),
i.e. n=4, k=3:
All elements of array C of size 4 (k+1) are
initialized to ZERO.
i.e. C[0] = C[1] = C[2] = C[3] = C[4] = 0;
Then C[0] is set to 1
For i = 1:
C[1] = C[1] + C[0] = 0 + 1 = 1 ==>> C(1,1) = 1
For i = 2:
C[2] = C[2] + C[1] = 0 + 1 = 1 ==>> C(2,2) = 1
C[1] = C[1] + C[0] = 1 + 1 = 2 ==>> C(2,1) = 2
For i=3:
C[3] = C[3] + C[2] = 0 + 1 = 1 ==>> C(3,3) = 1
C[2] = C[2] + C[1] = 1 + 2 = 3 ==>> C(3,2) = 3
C[1] = C[1] + C[0] = 2 + 1 = 3 ==>> C(3,1) = 3
For i=4:
C[4] = C[4] + C[3] = 0 + 1 = 1 ==>> C(4,4) = 1
C[3] = C[3] + C[2] = 1 + 3 = 4 ==>> C(4,3) = 4
C[2] = C[2] + C[1] = 3 + 3 = 6 ==>> C(4,2) = 6
C[1] = C[1] + C[0] = 3 + 1 = 4 ==>> C(4,1) = 4
C(4,3) = 4 is would be the answer in our example.
记忆方法:这个想法是创建一个查找表并遵循递归自顶向下的方法。在计算任何值之前,我们检查它是否已经在查找表中。如果是,我们返回值。否则,我们计算该值并将其存储在查找表中。以下是动态规划的自顶向下方法来寻找二项式系数的值。
C++
// A Dynamic Programming based
// solution that uses
// table dp[][] to calculate
// the Binomial Coefficient
// A naive recursive approach
// with table C++ implementation
#include
using namespace std;
// Returns value of Binomial Coefficient C(n, k)
int binomialCoeffUtil(int n, int k, int** dp)
{
// If value in lookup table then return
if (dp[n][k] != -1) //
return dp[n][k];
// store value in a table before return
if (k == 0) {
dp[n][k] = 1;
return dp[n][k];
}
// store value in table before return
if (k == n) {
dp[n][k] = 1;
return dp[n][k];
}
// save value in lookup table before return
dp[n][k] = binomialCoeffUtil(n - 1, k - 1, dp) +
binomialCoeffUtil(n - 1, k, dp);
return dp[n][k];
}
int binomialCoeff(int n, int k)
{
int** dp; // make a temporary lookup table
dp = new int*[n + 1];
// loop to create table dynamically
for (int i = 0; i < (n + 1); i++) {
dp[i] = new int[k + 1];
}
// nested loop to initialise the table with -1
for (int i = 0; i < (n + 1); i++) {
for (int j = 0; j < (k + 1); j++) {
dp[i][j] = -1;
}
}
return binomialCoeffUtil(n, k, dp);
}
/* Driver code*/
int main()
{
int n = 5, k = 2;
cout << "Value of C(" << n << ", " << k << ") is "
<< binomialCoeff(n, k) << endl;
return 0;
}
// This is code is contributed by MOHAMMAD MUDASSIR
Java
// A Dynamic Programming based
// solution that uses
// table dp[][] to calculate
// the Binomial Coefficient
// A naive recursive approach
// with table Java implementation
import java.util.*;
class GFG{
// Returns value of Binomial
// Coefficient C(n, k)
static int binomialCoeffUtil(int n, int k,
Vector []dp)
{
// If value in lookup table
// then return
if (dp[n].get(k) != -1)
return dp[n].get(k);
// store value in a table
// before return
if (k == 0)
{
dp[n].add(k, 1);
return dp[n].get(k);
}
// store value in table
// before return
if (k == n)
{
dp[n].add(k, 1);
return dp[n].get(k);
}
// save value in lookup table
// before return
dp[n].add(k, binomialCoeffUtil(n - 1,
k - 1, dp) +
binomialCoeffUtil(n - 1,
k, dp));
return dp[n].get(k);
}
static int binomialCoeff(int n, int k)
{
// Make a temporary lookup table
Vector []dp = new Vector[n+1];
// Loop to create table dynamically
for (int i = 0; i < (n + 1); i++)
{
dp[i] = new Vector();
for(int j = 0; j <= k; j++)
dp[i].add(-1);
}
return binomialCoeffUtil(n, k, dp);
}
// Driver code
public static void main(String[] args)
{
int n = 5, k = 2;
System.out.print("Value of C(" + n +
", " + k + ") is " +
binomialCoeff(n, k) + "\n");
}
}
// This code is contributed by Rajput-Ji
蟒蛇3
# A Dynamic Programming based solution
# that uses table dp[][] to calculate
# the Binomial Coefficient. A naive
# recursive approach with table
# Python3 implementation
# Returns value of Binomial
# Coefficient C(n, k)
def binomialCoeffUtil(n, k, dp):
# If value in lookup table then return
if dp[n][k] != -1:
return dp[n][k]
# Store value in a table before return
if k == 0:
dp[n][k] = 1
return dp[n][k]
# Store value in table before return
if k == n:
dp[n][k] = 1
return dp[n][k]
# Save value in lookup table before return
dp[n][k] = (binomialCoeffUtil(n - 1, k - 1, dp) +
binomialCoeffUtil(n - 1, k, dp))
return dp[n][k]
def binomialCoeff(n, k):
# Make a temporary lookup table
dp = [ [ -1 for y in range(k + 1) ]
for x in range(n + 1) ]
return binomialCoeffUtil(n, k, dp)
# Driver code
n = 5
k = 2
print("Value of C(" + str(n) +
", " + str(k) + ") is",
binomialCoeff(n, k))
# This is code is contributed by Prateek Gupta
C#
// C# program for the
// above approach
// A Dynamic Programming based
// solution that uses
// table [,]dp to calculate
// the Binomial Coefficient
// A naive recursive approach
// with table C# implementation
using System;
using System.Collections.Generic;
class GFG{
// Returns value of Binomial
// Coefficient C(n, k)
static int binomialCoeffUtil(int n, int k,
List []dp)
{
// If value in lookup table
// then return
if (dp[n][k] != -1)
return dp[n][k];
// store value in a table
// before return
if (k == 0)
{
dp[n][k] = 1;
return dp[n][k];
}
// store value in table
// before return
if (k == n)
{
dp[n][k] = 1;
return dp[n][k];
}
// save value in lookup table
// before return
dp[n][k] = binomialCoeffUtil(n - 1,
k - 1, dp) +
binomialCoeffUtil(n - 1,
k, dp);
return dp[n][k];
}
static int binomialCoeff(int n, int k)
{
// Make a temporary lookup table
List []dp = new List[n + 1];
// Loop to create table dynamically
for (int i = 0; i < (n + 1); i++)
{
dp[i] = new List();
for(int j = 0; j <= k; j++)
dp[i].Add(-1);
}
return binomialCoeffUtil(n, k, dp);
}
// Driver code
public static void Main(String[] args)
{
int n = 5, k = 2;
Console.Write("Value of C(" + n +
", " + k + ") is " +
binomialCoeff(n, k) + "\n");
}
}
// This code is contributed by 29AjayKumar
Javascript
Value of C(5, 2) is 10
取消分子和分母之间的因数:
nCr = (n-r+1)*(n-r+2)*….*n / (r!)
创建一个从 n-r+1 到 n 的数字数组 arr,其大小为 r。由于 nCr 始终是整数,因此分母中的所有数字都应与分子(由 arr 表示)的乘积相抵消。
对于 i = 1 到 i = r,
搜索 arr,如果 arr[j] 和 i 有 gcd>1,则除以 gcd,当 i 变为 1 时,停止搜索
现在,答案只是 arr 的乘积,其值 mod 10^9+7 可以使用单次传递找到,公式使用 (a*b)%mod = (a%mod * b%mod)%mod
Java
import java.util.*;
class GFG
{
static int gcd(int a, int b) // function to find gcd of two numbers in O(log(min(a,b)))
{
if(b==0) return a;
return gcd(b,a%b);
}
static int nCr(int n, int r)
{
if(r>n) // base case
return 0;
if(r>n-r) // C(n,r) = C(n,n-r) better time complexity for lesser r value
r = n-r;
int mod = 1000000007;
int[] arr = new int[r]; // array of elements from n-r+1 to n
for(int i=n-r+1; i<=n; i++)
{
arr[i+r-n-1] = i;
}
long ans = 1;
for(int k=1;k1
{
int j=0, i=k;
while(j1)
{
arr[j] /= x; // if gcd>1, divide both by gcd
i /= x;
}
if(i==1)
break; // if i becomes 1, no need to search arr
j += 1;
}
}
for(int i : arr) // single pass to multiply the numerator
ans = (ans*i)%mod;
return (int)ans;
}
// Driver code
public static void main(String[] args)
{
int n = 5, r = 2;
System.out.print("Value of C(" + n+ ", " + r+ ") is "
+nCr(n, r) +"\n");
}
}
// This code is contributed by Gautam Wadhwani
蟒蛇3
import math
class GFG:
def nCr(self, n, r):
def gcd(a,b): # function to find gcd of two numbers in O(log(min(a,b)))
if b==0: # base case
return a
return gcd(b,a%b)
if r>n:
return 0
if r>n-r: # C(n,r) = C(n,n-r) better time complexity for lesser r value
r = n-r
mod = 10**9 + 7
arr = list(range(n-r+1,n+1)) # array of elements from n-r+1 to n
ans = 1
for i in range(1,r+1): # for numbers from 1 to r find arr[j] such that gcd(i,arr[j])>1
j=0
while j1:
arr[j] //= x # if gcd>1, divide both by gcd
i //= x
if arr[j]==1: # if element becomes 1, its of no use anymore so delete from arr
del arr[j]
j -= 1
if i==1:
break # if i becomes 1, no need to search arr
j += 1
for i in arr: # single pass to multiply the numerator
ans = (ans*i)%mod
return ans
# Driver code
n = 5
k = 2
ob = GFG()
print("Value of C(" + str(n) +
", " + str(k) + ") is",
ob.nCr(n, k))
# This is code is contributed by Gautam Wadhwani
C#
using System;
class GFG{
// Function to find gcd of two numbers
// in O(log(min(a,b)))
static int gcd(int a, int b)
{
if (b == 0)
return a;
return gcd(b, a % b);
}
static int nCr(int n, int r)
{
// Base case
if (r > n)
return 0;
// C(n,r) = C(n,n-r) better time
// complexity for lesser r value
if (r > n - r)
r = n - r;
int mod = 1000000007;
// Array of elements from n-r+1 to n
int[] arr = new int[r];
for(int i = n - r + 1; i <= n; i++)
{
arr[i + r - n - 1] = i;
}
long ans = 1;
// For numbers from 1 to r find arr[j]
// such that gcd(i,arr[j])>1
for(int k = 1; k < r + 1; k++)
{
int j = 0, i = k;
while (j < arr.Length)
{
int x = gcd(i,arr[j]);
if (x > 1)
{
// If gcd>1, divide both by gcd
arr[j] /= x;
i /= x;
}
if (i == 1)
// If i becomes 1, no need
// to search arr
break;
j += 1;
}
}
// Single pass to multiply the numerator
foreach(int i in arr)
ans = (ans * i) % mod;
return (int)ans;
}
// Driver code
static public void Main()
{
int n = 5, r = 2;
Console.WriteLine("Value of C(" + n +
", " + r + ") is " +
nCr(n, r) + "\n");
}
}
// This code is contributed by rag2127
Value of C(5, 2) is 10
时间复杂度: O(( min(r, nr)^2 ) * log(n)),当 n >> r 或 n >> (nr) 时有用
辅助空间: O(min(r, nr))
以对数时间查看 GCD
使用 Eratosthenes 筛法对从 1 到 n 的每个数字进行质因数分解:
1. 创建一个大小为 n+1 的数组 SPF 到从 1 到 n 的每个数字的最小素因数
Set SPF[i] = i for all i = 1 to i = n
2. 使用埃拉托色尼筛子:
for i = 2 to i = n:
if i is prime,
for all multiples j of i, j<=n:
if SPF[j] equals j, set SPF[j] = i
3. 一旦我们知道从 1 到 n 的每个数的 SPF,我们可以在 O(log(n)) 时间内使用 SPF 的递归除法找到从 1 到 n 的任何数的素因数分解,直到该数变为 1
Now, nCr = (n-r+1)*(r+2)* ... *(n) / (r)!
4.创建一个字典(或hashmap)来存储nCr实际值的素数分解中每个素数的频率。
5. 因此,只需计算 nCr 中每个素数的频率并将它们相乘,以提高其频率的幂。
6. 对于分子,迭代 i = n-r+1 到 i = n,对于 i 的所有质因子,将它们的频率存储在字典中。
( prime_pow[prime_factor] += freq_in_i )
7. 对于分母,迭代 i = 1 到 i = r,现在减去频率而不是增加频率。
8. 现在,遍历字典并将答案乘以 (prime ^ prime_pow[prime]) % (10^9 + 7)
ans = (ans * pow(prime, prime_pow[prime], mod) ) % mod
Java
import java.util.*;
class GFG {
// pow(base,exp,mod) is used to find
// (base^exp)%mod fast -> O(log(exp))
static long pow(long b, long exp, long mod)
{
long ret = 1;
while (exp > 0) {
if ((exp & 1) > 0)
ret = (ret * b) % mod;
b = (b * b) % mod;
exp >>= 1;
}
return ret;
}
static int nCr(int n, int r)
{
if (r > n) // base case
return 0;
// C(n,r) = C(n,n-r) Complexity for
// this code is lesser for lower n-r
if (n - r > r)
r = n - r;
// list to smallest prime factor
// of each number from 1 to n
int[] SPF = new int[n + 1];
// set smallest prime factor of each
// number as itself
for (int i = 1; i <= n; i++)
SPF[i] = i;
// set smallest prime factor of all
// even numbers as 2
for (int i = 4; i <= n; i += 2)
SPF[i] = 2;
for (int i = 3; i * i < n + 1; i += 2)
{
// Check if i is prime
if (SPF[i] == i)
{
// All multiples of i are
// composite (and divisible by
// i) so add i to their prime
// factorization getpow(j,i)
// times
for (int j = i * i; j < n + 1; j += i)
if (SPF[j] == j) {
SPF[j] = i;
}
}
}
// Hash Map to store power of
// each prime in C(n,r)
Map prime_pow
= new HashMap<>();
// For numerator count frequency of each prime factor
for (int i = r + 1; i < n + 1; i++)
{
int t = i;
// Recursive division to find
// prime factorization of i
while (t > 1)
{
prime_pow.put(SPF[t],
prime_pow.getOrDefault(SPF[t], 0) + 1);
t /= SPF[t];
}
}
// For denominator subtract the power of
// each prime factor
for (int i = 1; i < n - r + 1; i++)
{
int t = i;
// Recursive division to find
// prime factorization of i
while (t > 1)
{
prime_pow.put(SPF[t],
prime_pow.get(SPF[t]) - 1);
t /= SPF[t];
}
}
// long because mod is large and a%mod
// * b%mod can overflow int
long ans = 1, mod = 1000000007;
// use (a*b)%mod = (a%mod * b%mod)%mod
for (int i : prime_pow.keySet())
// pow(base,exp,mod) is used to
// find (base^exp)%mod fast
ans = (ans * pow(i, prime_pow.get(i), mod))
% mod;
return (int)ans;
}
// Driver code
public static void main(String[] args)
{
int n = 5, r = 2;
System.out.print("Value of C(" + n + ", " + r
+ ") is " + nCr(n, r) + "\n");
}
}
// This code is contributed by Gautam Wadhwani
蟒蛇3
# Python code for the above approach
import math
class GFG:
def nCr(self, n, r):
# Base case
if r > n:
return 0
# C(n,r) = C(n,n-r) Complexity for this
# code is lesser for lower n-r
if n - r > r:
r = n - r
# List to store smallest prime factor
# of every number from 1 to n
SPF = [i for i in range(n+1)]
for i in range(4, n+1, 2):
# set smallest prime factor of
# all even numbers as 2
SPF[i] = 2
for i in range(3, n+1, 2):
if i*i > n:
break
# Check if i is prime
if SPF[i] == i:
# All multiples of i are composite
# (and divisible by i) so add i to
# their prime factorization getpow(j,i) times
for j in range(i*i, n+1, i):
if SPF[j] == j:
# set smallest prime factor
# of j to i only if it is
# not previously set
SPF[j] = i
# dictionary to store power of each prime in C(n,r)
prime_pow = {}
# For numerator count frequency
# of each prime factor
for i in range(r+1, n+1):
t = i
# Recursive division to
# find prime factorization of i
while t > 1:
if not SPF[t] in prime_pow:
prime_pow[SPF[t]] = 1
else:
prime_pow[SPF[t]] += 1
t //= SPF[t]
# For denominator subtract the
# power of each prime factor
for i in range(1, n-r+1):
t = i
# Recursive division to
# find prime factorization of i
while t > 1:
prime_pow[SPF[t]] -= 1
t //= SPF[t]
ans = 1
mod = 10**9 + 7
# Use (a*b)%mod = (a%mod * b%mod)%mod
for i in prime_pow:
# pow(base,exp,mod) is used to
# find (base^exp)%mod fast
ans = (ans*pow(i, prime_pow[i], mod)) % mod
return ans
# Driver code
n = 5
k = 2
ob = GFG()
print("Value of C(" + str(n) +
", " + str(k) + ") is",
ob.nCr(n, k))
# This is code is contributed by Gautam Wadhwani
Value of C(5, 2) is 10
时间复杂度: O(n*log(n)),当 r->n/2 时非常有用
辅助空间: O(n)
请参阅 O(log(n)) 中的质数分解
另一种方法:(模块化反演技术)
1. nCr 的通式为 ( n*(n-1)*(n-2)* … *(n-r+1) ) / (r!)。我们可以直接用这个公式来求nCr。但这会溢出。我们需要找到 nCr mod m 以便它不会溢出。我们可以很容易地用模算术的公式来做到这一点。
for the n*(n-1)*(n-2)* ... *(n-r+1) part we can use the formula,
(a*b) mod m = ((a % m) * (b % m)) % m
2.对于1/r!部分,我们需要找到从 1 到 r 的每个数字的模逆。然后使用上面相同的公式和 1 到 r 的模逆。我们可以使用公式在 O(r) 时间内找到模逆,
inv[1] = 1
inv[i] = − ⌊m/i⌋ * inv[m mod i] mod m
To use this formula, m has to be a prime.
在练习题中,我们需要用模 1000000007 显示答案,这是一个质数。
所以,这种技术会奏效。
C++
// C++ program for the above approach
#include
using namespace std;
// Function to find binomial
// coefficient
int binomialCoeff(int n, int r)
{
if (r > n)
return 0;
long long int m = 1000000007;
long long int inv[r + 1] = { 0 };
inv[0] = 1;
if(r+1>=2)
inv[1] = 1;
// Getting the modular inversion
// for all the numbers
// from 2 to r with respect to m
// here m = 1000000007
for (int i = 2; i <= r; i++) {
inv[i] = m - (m / i) * inv[m % i] % m;
}
int ans = 1;
// for 1/(r!) part
for (int i = 2; i <= r; i++) {
ans = ((ans % m) * (inv[i] % m)) % m;
}
// for (n)*(n-1)*(n-2)*...*(n-r+1) part
for (int i = n; i >= (n - r + 1); i--) {
ans = ((ans % m) * (i % m)) % m;
}
return ans;
}
/* Driver code*/
int main()
{
int n = 5, r = 2;
cout << "Value of C(" << n << ", " << r << ") is "
<< binomialCoeff(n, r) << endl;
return 0;
}
Java
// JAVA program for the above approach
import java.util.*;
class GFG
{
// Function to find binomial
// coefficient
static int binomialCoeff(int n, int r)
{
if (r > n)
return 0;
long m = 1000000007;
long inv[] = new long[r + 1];
inv[0] = 1;
if(r+1>=2)
inv[1] = 1;
// Getting the modular inversion
// for all the numbers
// from 2 to r with respect to m
// here m = 1000000007
for (int i = 2; i <= r; i++) {
inv[i] = m - (m / i) * inv[(int) (m % i)] % m;
}
int ans = 1;
// for 1/(r!) part
for (int i = 2; i <= r; i++) {
ans = (int) (((ans % m) * (inv[i] % m)) % m);
}
// for (n)*(n-1)*(n-2)*...*(n-r+1) part
for (int i = n; i >= (n - r + 1); i--) {
ans = (int) (((ans % m) * (i % m)) % m);
}
return ans;
}
/* Driver code*/
public static void main(String[] args)
{
int n = 5, r = 2;
System.out.print("Value of C(" + n+ ", " + r+ ") is "
+binomialCoeff(n, r) +"\n");
}
}
// This code contributed by Rajput-Ji
蟒蛇3
# Python3 program for the above approach
# Function to find binomial
# coefficient
def binomialCoeff(n, r):
if (r > n):
return 0
m = 1000000007
inv = [0 for i in range(r + 1)]
inv[0] = 1;
if(r+1>=2)
inv[1] = 1;
# Getting the modular inversion
# for all the numbers
# from 2 to r with respect to m
# here m = 1000000007
for i in range(2, r + 1):
inv[i] = m - (m // i) * inv[m % i] % m
ans = 1
# for 1/(r!) part
for i in range(2, r + 1):
ans = ((ans % m) * (inv[i] % m)) % m
# for (n)*(n-1)*(n-2)*...*(n-r+1) part
for i in range(n, n - r, -1):
ans = ((ans % m) * (i % m)) % m
return ans
# Driver code
n = 5
r = 2
print("Value of C(" ,n , ", " , r ,
") is ",binomialCoeff(n, r))
# This code is contributed by rohan07
C#
// C# program for the above approach
using System;
public class GFG
{
// Function to find binomial
// coefficient
static int binomialCoeff(int n, int r)
{
if (r > n)
return 0;
long m = 1000000007;
long []inv = new long[r + 1];
inv[0] = 1;
if(r+1>=2)
inv[1] = 1;
// Getting the modular inversion
// for all the numbers
// from 2 to r with respect to m
// here m = 1000000007
for (int i = 2; i <= r; i++) {
inv[i] = m - (m / i) * inv[(int) (m % i)] % m;
}
int ans = 1;
// for 1/(r!) part
for (int i = 2; i <= r; i++) {
ans = (int) (((ans % m) * (inv[i] % m)) % m);
}
// for (n)*(n-1)*(n-2)*...*(n-r+1) part
for (int i = n; i >= (n - r + 1); i--) {
ans = (int) (((ans % m) * (i % m)) % m);
}
return ans;
}
/* Driver code*/
public static void Main(String[] args)
{
int n = 5, r = 2;
Console.Write("Value of C(" + n+ ", " + r+ ") is "
+binomialCoeff(n, r) +"\n");
}
}
// This code is contributed by 29AjayKumar
Javascript
Value of C(5, 2) is 10
时间复杂度: O(n+k)
辅助空间: O(k)
有关空间和时间效率的二项式系数,请参阅此内容
参考:
http://www.csl.mtu.edu/cs4321/www/Lectures/Lecture%2015%20-%20Dynamic%20Programming%20Binomial%20Coefficients.htm
https://cp-algorithms.com/algebra/module-inverse.html
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。