Related Articles
Count ways to split N! into two distinct co-prime factors
• Last Updated : 13 Oct, 2020

Given an integer N, the task is to find the number of ways N! can be split into two distinct factors A and B such that A and B are co-primes. Since the answer can be very large, print it modulo 109 + 7.

Examples:

Input: N = 5
Output: 4
Explanation: The pairs are (1, 120), (3, 40), (5, 24), (8, 15).

Input: N = 7
Output: 8
Explanation: The pairs are (1, 5040), (5, 1008), (7, 720), (9, 560), (16, 315), (35, 144), (45, 112), (63, 80).

Naive Approach: The simplest approach is to calculate the factorial of N! and generate all its factors and check if any pair of factors (i, j) has GCD(i, j) == 1

Time Complexity: O(√N!)
Auxiliary Space: O(1)

Efficient Approach: To optimize the above approach, the idea is to find distinct prime factors of N and then count ways to split it into two distinct co-prime factors A & B. Follow the steps below to solve the problem:

• Every positive integer can be represented as a product of powers of primes (prime factorization). Therefore, every possible value of N can be expressed as N = 2p × 3q × 5r…..(p ≥ 0, q ≥ 0, r ≥ 0).
• Now, the task is to split N into two distinct co-prime factors. This can be done by assigning each of the terms in prime factorization of N into two possible combinations each time.

Illustration:

Let N = 18900
Expressing N in the form of its prime factors, 18900 = 22 * 33 * 52 * 71

Each of 22, 33, 52 and 71 can be assigned to either of the two factors. Using product rule in combinatorics, the total possible ways are 24 = 16. Since the two factors have no order, the total possible ways are 23 = 8. Therefore, the number of ways N is 2X – 1, where X is the number of prime-factors of N.

Follow the steps below to solve the problem:

1. The prime factorization of N! contains all primes which are less than or equal to N.
2. If x is the count of primes less than or equal to N, then the number of ways N! (factorial) can be split into two distinct co-prime factors is equal to 2x – 1.
3. Precompute the number of primes ∀ n ≤ N using Sieve of Eratosthenes and store them in an array.
4. To calculate the result modulo 109 + 7, use Modular Exponentiation i.e. calculate xy % p.

Below is the implementation of the above approach:

## C++

 `// C++ Program for the above approach` `#include ` `using` `namespace` `std;`   `// Maximum value of N` `#define MAXN 1000000`   `// Stores at each indices if` `// given number is prime or not` `int` `is_prime[MAXN] = { 0 };`   `// Stores count_of_primes` `int` `count_of_primes[MAXN] = { 0 };`   `// Function to generate primes` `// using Sieve of Eratsothenes` `void` `sieve()` `{` `    ``for` `(``int` `i = 3; i < MAXN; i += 2) {`   `        ``// Assume all odds are primes` `        ``is_prime[i] = 1;` `    ``}`   `    ``for` `(``int` `i = 3; i * i < MAXN; i += 2) {`   `        ``// If a prime is encountered` `        ``if` `(is_prime[i])`   `            ``for` `(``int` `j = i * i; j < MAXN;` `                 ``j += i) {`   `                ``// Mark all its multiples` `                ``// as non-prime` `                ``is_prime[j] = 0;` `            ``}` `    ``}`   `    ``is_prime = 1;`   `    ``// Count primes <= MAXN` `    ``for` `(``int` `i = 1; i < MAXN; i++)` `        ``count_of_primes[i]` `            ``= count_of_primes[i - 1]` `              ``+ is_prime[i];` `}`   `// Function to calculate (x ^ y) % p` `// in O(log y)` `long` `long` `int` `power(``long` `long` `int` `x,` `                    ``long` `long` `int` `y,` `                    ``long` `long` `int` `p)` `{` `    ``long` `long` `result = 1;` `    ``while` `(y > 0) {` `        ``if` `(y & 1 == 1)` `            ``result = (result * x) % p;` `        ``x = (x * x) % p;` `        ``y >>= 1;` `    ``}` `    ``return` `result;` `}`   `// Utility function to count the number of ways` `// N! can be split into co-prime factors` `void` `numberOfWays(``int` `N)` `{` `    ``long` `long` `int` `count` `        ``= count_of_primes[N] - 1;` `    ``long` `long` `int` `mod = 1000000007;` `    ``long` `long` `int` `answer` `        ``= power(2, count, mod);`   `    ``if` `(N == 1)` `        ``answer = 0;`   `    ``cout << answer;` `}`   `// Driver Code` `int` `main()` `{` `    ``// Calling sieve function` `    ``sieve();`   `    ``// Given N` `    ``int` `N = 7;`   `    ``// Function call` `    ``numberOfWays(N);`   `    ``return` `0;` `}`

## Java

 `// Java Program for the above approach` `import` `java.util.*;`   `class` `GFG {`   `    ``// Maximum value of N` `    ``static` `final` `int` `MAXN = ``1000000``;`   `    ``// Stores at each indices if` `    ``// given number is prime or not` `    ``static` `int` `is_prime[];`   `    ``// Stores count_of_primes` `    ``static` `int` `count_of_primes[];`   `    ``// Function to generate primes` `    ``// using Sieve of Eratsothenes` `    ``static` `void` `sieve()` `    ``{` `        ``is_prime = ``new` `int``[MAXN];` `        ``count_of_primes = ``new` `int``[MAXN];` `        ``Arrays.fill(is_prime, ``0``);` `        ``Arrays.fill(count_of_primes, ``0``);`   `        ``for` `(``int` `i = ``3``; i < MAXN; i += ``2``) {`   `            ``// Assume all odds are primes` `            ``is_prime[i] = ``1``;` `        ``}`   `        ``for` `(``int` `i = ``3``; i * i < MAXN; i += ``2``) {`   `            ``// If a prime is encountered` `            ``if` `(is_prime[i] == ``1``) {` `                ``for` `(``int` `j = i * i; j < MAXN;` `                     ``j += i) {` `                    ``// MArk all its multiples` `                    ``// as non-prime` `                    ``is_prime[j] = ``0``;` `                ``}` `            ``}` `        ``}`   `        ``is_prime[``2``] = ``1``;`   `        ``// Count all primes upto MAXN` `        ``for` `(``int` `i = ``1``; i < MAXN; i++)` `            ``count_of_primes[i]` `                ``= count_of_primes[i - ``1``] + is_prime[i];` `    ``}`   `    ``// Function to calculate (x ^ y) % p` `    ``// in O(log y)` `    ``static` `long` `power(``long` `x, ``long` `y, ``long` `p)` `    ``{` `        ``long` `result = ``1``;` `        ``while` `(y > ``0``) {` `            ``if` `((y & ``1``) == ``1``)` `                ``result = (result * x) % p;` `            ``x = (x * x) % p;` `            ``y >>= ``1``;` `        ``}` `        ``return` `result;` `    ``}`   `    ``// Utility function to count the number of` `    ``// ways N! can be split into two co-prime factors` `    ``static` `void` `numberOfWays(``int` `N)` `    ``{` `        ``long` `count = count_of_primes[N] - ``1``;` `        ``long` `mod = ``1000000007``;` `        ``long` `answer = power(``2``, count, mod);` `        ``if` `(N == ``1``)` `            ``answer = ``0``;` `        ``long` `ans = answer;` `        ``System.out.println(ans);` `    ``}`   `    ``// Driver Code` `    ``public` `static` `void` `main(String[] args)` `    ``{`   `        ``// Calling sieve function` `        ``sieve();`   `        ``// Given N` `        ``int` `N = ``7``;`   `        ``// Function call` `        ``numberOfWays(N);` `    ``}` `}`

## Python3

 `# Python3 program for the above approach` `import` `math`   `# Maximum value of N` `MAXN ``=` `1000000`   `# Stores at each indices if` `# given number is prime or not` `is_prime ``=` `[``0``] ``*` `MAXN`   `# Stores count_of_primes` `count_of_primes ``=` `[``0``] ``*` `MAXN`   `# Function to generate primes` `# using Sieve of Eratsothenes` `def` `sieve():` `    `  `    ``for` `i ``in` `range``(``3``, MAXN, ``2``):` `        `  `        ``# Assume all odds are primes` `        ``is_prime[i] ``=` `1`   `    ``for` `i ``in` `range``(``3``, ``int``(math.sqrt(MAXN)), ``2``):`   `        ``# If a prime is encountered` `        ``if` `is_prime[i]:` `            ``for` `j ``in` `range``(i ``*` `i, MAXN, i):`   `                ``# Mark all its multiples` `                ``# as non-prime` `                ``is_prime[j] ``=` `0`   `    ``is_prime[``2``] ``=` `1`   `    ``# Count primes <= MAXN` `    ``for` `i ``in` `range``(``1``, MAXN):` `        ``count_of_primes[i] ``=` `(count_of_primes[i ``-` `1``] ``+` `                                     ``is_prime[i])`   `# Function to calculate (x ^ y) % p` `# in O(log y)` `def` `power(x, y, p):` `  `  `    ``result ``=` `1` `    ``while` `(y > ``0``):` `        ``if` `y & ``1` `=``=` `1``:` `            ``result ``=` `(result ``*` `x) ``%` `p` `            `  `        ``x ``=` `(x ``*` `x) ``%` `p` `        ``y >>``=` `1`   `    ``return` `result`   `# Utility function to count the number of ways` `# N! can be split into co-prime factors` `def` `numberOfWays(N):` `  `  `    ``count ``=` `count_of_primes[N] ``-` `1` `    ``mod ``=` `1000000007` `    ``answer ``=` `power(``2``, count, mod)`   `    ``if` `N ``=``=` `1``:` `        ``answer ``=` `0`   `    ``print``(answer)`   `# Driver Code` `if` `__name__ ``=``=` `"__main__"``:` `  `  `    ``# Calling sieve function` `    ``sieve()`   `    ``# Given N` `    ``N ``=` `7`   `    ``# Function call` `    ``numberOfWays(N)`   `# This code is contributed by akhilsaini`

## C#

 `// C# program for the above approach ` `using` `System;`   `class` `GFG{`   `// Maximum value of N` `static` `int` `MAXN = 1000000;`   `// Stores at each indices if` `// given number is prime or not` `static` `int``[] is_prime;`   `// Stores count_of_primes` `static` `int``[] count_of_primes;`   `// Function to generate primes` `// using Sieve of Eratsothenes` `static` `void` `sieve()` `{` `    ``is_prime = ``new` `int``[MAXN];` `    ``count_of_primes = ``new` `int``[MAXN];` `    ``Array.Fill(is_prime, 0);` `    ``Array.Fill(count_of_primes, 0);`   `    ``for``(``int` `i = 3; i < MAXN; i += 2) ` `    ``{` `        `  `        ``// Assume all odds are primes` `        ``is_prime[i] = 1;` `    ``}`   `    ``for``(``int` `i = 3; i * i < MAXN; i += 2) ` `    ``{` `        `  `        ``// If a prime is encountered` `        ``if` `(is_prime[i] == 1) ` `        ``{` `            ``for``(``int` `j = i * i; j < MAXN; j += i)` `            ``{` `                `  `                ``// MArk all its multiples` `                ``// as non-prime` `                ``is_prime[j] = 0;` `            ``}` `        ``}` `    ``}`   `    ``is_prime = 1;`   `    ``// Count all primes upto MAXN` `    ``for``(``int` `i = 1; i < MAXN; i++)` `        ``count_of_primes[i] = count_of_primes[i - 1] +` `                                    ``is_prime[i];` `}`   `// Function to calculate (x ^ y) % p` `// in O(log y)` `static` `long` `power(``long` `x, ``long` `y, ``long` `p)` `{` `    ``long` `result = 1;` `    ``while` `(y > 0)` `    ``{` `        ``if` `((y & 1) == 1)` `            ``result = (result * x) % p;` `            `  `        ``x = (x * x) % p;` `        ``y >>= 1;` `    ``}` `    ``return` `result;` `}`   `// Utility function to count the number of` `// ways N! can be split into two co-prime factors` `static` `void` `numberOfWays(``int` `N)` `{` `    ``long` `count = count_of_primes[N] - 1;` `    ``long` `mod = 1000000007;` `    ``long` `answer = power(2, count, mod);` `    `  `    ``if` `(N == 1)` `        ``answer = 0;` `        `  `    ``long` `ans = answer;` `    ``Console.Write(ans);` `}`   `// Driver Code` `public` `static` `void` `Main()` `{` `    `  `    ``// Calling sieve function` `    ``sieve();`   `    ``// Given N` `    ``int` `N = 7;`   `    ``// Function call` `    ``numberOfWays(N);` `}` `}`   `// This code is contributed by akhilsaini`

Output:

```8

```

Time Complexity: O(log(log(N)) + log(N))
Auxiliary Space: O(N)

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.

My Personal Notes arrow_drop_up
Recommended Articles
Page :