N 和 K 组合因子的计数 (nCk)
给定整数N和K ,任务是找到N C K的因子数。由于答案可能非常大,因此返回以 998244353 为模的因子数。
例子:
Input: N = 5, K = 2
Output: 4
Explanation: 5C2 = 10 which have {1, 2, 5, 10} as its divisors. So answer would be 4.
Input: N = 10, K = 3
Output: 16
方法:这个问题可以基于以下数学事实来解决:
This value is always a whole number (Let’s say M).
where pi is a prime number.
Therefore, number of factors of M is
基于上述事实,可以通过求 M 的质因数及其指数来解决问题。求 M 的素因数,求分子的素因数和分母的素因数
请按照以下步骤解决问题:
- 使用埃拉托色尼筛法对前 K 个自然数进行素数分解以找到分母的素数。
- 类似地,对 [N – K +1, N] 范围内的自然数进行质因数分解以找到分子的质因数。
- 求出N C K的分子和分母中所有项的素因式分解后,使用上式求出N C K的因数个数。
下面是上述方法的实现:
C++
// C++ program to implement the approach
#include
using namespace std;
// Function to count the number of factors
int divisorsOfNchooseK(long long N, long long K)
{
// Parameter in time and space complexity
long long M = max((long long)sqrt(N), K);
// Sieve of eratosthenes for finding prime upto M
vector prime(M + 1, true);
prime[0] = prime[1] = false;
for (long long p = 2; p * p < prime.size(); p++) {
if (prime[p]) {
for (long long i = 2 * p; i < prime.size();
i += p) {
prime[i] = false;
}
}
}
// Store the denominator values in deno vector
vector deno(K + 1);
for (long long i = 1; i <= K; i++) {
deno[i] = i;
}
// Store the numerator values in nume vector
vector nume(K);
long long offset = N - K + 1;
for (long long i = 0; i < K; i++) {
nume[i] = offset + i;
}
// Variable for storing answer
long long ans = 1;
// Iterate through all prime upto M
for (long long p = 2; p < prime.size(); p++) {
if (prime[p]) {
// Store the power of p in
// prime factorization of C(N, K)
long long int power = 0;
// Do prime factorization of deno terms
for (long long i = p; i <= K; i += p) {
while (deno[i] % p == 0) {
power--;
deno[i] /= p;
}
}
// Do prime factorization of nume terms
for (long long i
= ((N - K + 1) + p - 1) / p * p;
i <= N; i += p) {
while (nume[i - offset] % p == 0) {
power++;
nume[i - offset] /= p;
}
}
ans *= (power + 1);
ans %= 998244353;
}
}
// Find whether any term in
// numerator is divisible by some prime
// greater than √N
for (long long i = N - K + 1; i <= N; i++) {
if (nume[i - offset] != 1) {
ans *= 2; // Coefficient of this prime will be 1
ans %= 998244353;
}
}
return ans;
}
// Driver code
int main()
{
long long N = 10, K = 3;
// Function call
int ans = divisorsOfNchooseK(N, K);
cout << ans;
return 0;
}
Java
// Java program to implement the approach
import java.util.*;
class GFG {
// Function to count the number of factors
static long divisorsOfNchooseK(long N, long K)
{
// Parameter in time and space complexity
long M = Math.max((long)Math.sqrt(N), K);
// Sieve of eratosthenes for finding prime upto M
boolean[] prime = new boolean[(int)M + 1];
for (long x = 0; x < M + 1; x++) {
prime[(int)x] = true;
}
prime[0] = prime[1] = false;
for (long p = 2; p * p < prime.length; p++) {
if (prime[(int)p] == true) {
for (long i = 2 * p; i < prime.length;
i += p) {
prime[(int)i] = false;
}
}
}
// Store the denominator values in deno vector
long[] deno = new long[(int)K + 1];
for (long i = 1; i <= K; i++) {
deno[(int)i] = i;
}
// Store the numerator values in nume vector
long[] nume = new long[(int)K];
long offset = N - K + 1;
for (long i = 0; i < K; i++) {
nume[(int)i] = offset + i;
}
// Variable for storing answer
long ans = 1;
// Iterate through all prime upto M
for (long p = 2; p < prime.length; p++) {
if (prime[(int)p] == true) {
// Store the power of p in
// prime factorization of C(N, K)
long power = 0;
// Do prime factorization of deno terms
for (long i = p; i <= K; i += p) {
while (deno[(int)i] % p == 0) {
power--;
deno[(int)i] /= p;
}
}
// Do prime factorization of nume terms
for (long i = ((N - K + 1) + p - 1) / p * p;
i <= N; i += p) {
while (nume[(int)(i - offset)] % p == 0) {
power++;
nume[(int)(i - offset)] /= p;
}
}
ans *= (power + 1);
ans %= 998244353;
}
}
// Find whether any term in
// numerator is divisible by some prime
// greater than √N
for (long i = N - K + 1; i <= N; i++) {
if (nume[(int)(i - offset)] != 1) {
ans *= 2; // Coefficient of this prime will
// be 1
ans %= 998244353;
}
}
return ans;
}
// Driver code
public static void main (String[] args) {
long N = 10, K = 3;
// Function call
long ans = divisorsOfNchooseK(N, K);
System.out.print(ans);
}
}
// This code is contributed by hrithikgarg03188.
Python3
# python3 program to implement the approach
import math
# Function to count the number of factors
def divisorsOfNchooseK(N, K) :
# Parameter in time and space complexity
M = max(int(math.sqrt(N)), K)
# Sieve of eratosthenes for finding prime upto M
prime = [ True for _ in range(M + 1) ]
prime[0] = prime[1] = False
for p in range(2, int(math.sqrt(len(prime)))) :
if (prime[p]) :
for i in range(2*p, len(prime), p) :
prime[i] = False
# Store the denominator values in deno vector
deno = [ 0 for _ in range(K + 1) ]
for i in range(1, K+1) :
deno[i] = i
# Store the numerator values in nume vector
nume = [ 0 for _ in range(K) ]
offset = N - K + 1
for i in range(0, K) :
nume[i] = offset + i
# Variable for storing answer
ans = 1
# Iterate through all prime upto M
for p in range(2, len(prime)) :
if (prime[p]) :
# Store the power of p in
# prime factorization of C(N, K)
power = 0
# Do prime factorization of deno terms
for i in range(p, K+1, p) :
while (deno[i] % p == 0) :
power -= 1
deno[i] //= p
# Do prime factorization of nume terms
for i in range(((N - K + 1) + p - 1) // p * p, N+1, p) :
while (nume[i - offset] % p == 0) :
power += 1
nume[i - offset] //= p
ans *= (power + 1)
ans %= 998244353
# Find whether any term in
# numerator is divisible by some prime
# greater than √N
for i in range(N - K + 1, N+1) :
if (nume[i - offset] != 1) :
ans *= 2 # Coefficient of this prime will be 1
ans %= 998244353
return ans
# Driver code
if __name__ == "__main__" :
N, K = 10, 3
# Function call
ans = divisorsOfNchooseK(N, K)
print(ans)
# This code is contributed by rakeshsahni
C#
// C# program to implement the approach
using System;
class GFG {
// Function to count the number of factors
static long divisorsOfNchooseK(long N, long K)
{
// Parameter in time and space complexity
long M = Math.Max((long)Math.Sqrt(N), K);
// Sieve of eratosthenes for finding prime upto M
bool[] prime = new bool[M + 1];
for (long x = 0; x < M + 1; x++) {
prime[x] = true;
}
prime[0] = prime[1] = false;
for (long p = 2; p * p < prime.Length; p++) {
if (prime[p] == true) {
for (long i = 2 * p; i < prime.Length;
i += p) {
prime[i] = false;
}
}
}
// Store the denominator values in deno vector
long[] deno = new long[K + 1];
for (long i = 1; i <= K; i++) {
deno[i] = i;
}
// Store the numerator values in nume vector
long[] nume = new long[K];
long offset = N - K + 1;
for (long i = 0; i < K; i++) {
nume[i] = offset + i;
}
// Variable for storing answer
long ans = 1;
// Iterate through all prime upto M
for (long p = 2; p < prime.Length; p++) {
if (prime[p] == true) {
// Store the power of p in
// prime factorization of C(N, K)
long power = 0;
// Do prime factorization of deno terms
for (long i = p; i <= K; i += p) {
while (deno[i] % p == 0) {
power--;
deno[i] /= p;
}
}
// Do prime factorization of nume terms
for (long i = ((N - K + 1) + p - 1) / p * p;
i <= N; i += p) {
while (nume[i - offset] % p == 0) {
power++;
nume[i - offset] /= p;
}
}
ans *= (power + 1);
ans %= 998244353;
}
}
// Find whether any term in
// numerator is divisible by some prime
// greater than √N
for (long i = N - K + 1; i <= N; i++) {
if (nume[i - offset] != 1) {
ans *= 2; // Coefficient of this prime will
// be 1
ans %= 998244353;
}
}
return ans;
}
// Driver code
public static void Main()
{
long N = 10, K = 3;
// Function call
long ans = divisorsOfNchooseK(N, K);
Console.Write(ans);
}
}
// This code is contributed by Samim Hossain Mondal.
Javascript
输出
16
时间复杂度: O(M * loglogM)
辅助空间: O(M) 其中 M 为最大值(√N, K)