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 * 71Each 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:
- The prime factorization of N! contains all primes which are less than or equal to N.
- 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.
- Precompute the number of primes ? n ? N using Sieve of Eratosthenes and store them in an array.
- 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 <bits/stdc++.h>using namespace std;Â
// Maximum value of N#define MAXN 1000000Â
// Stores at each indices if// given number is prime or notint is_prime[MAXN] = { 0 };Â
// Stores count_of_primesint count_of_primes[MAXN] = { 0 };Â
// Function to generate primes// using Sieve of Eratosthenesvoid 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[2] = 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 factorsvoid 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 Codeint main(){    // Calling sieve function    sieve();Â
    // Given N    int N = 7;Â
    // Function call    numberOfWays(N);Â
    return 0;} |
Java
// Java Program for the above approachimport 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 Eratosthenes    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 approachimport mathÂ
# Maximum value of NMAXN = 1000000Â
# Stores at each indices if# given number is prime or notis_prime = [0] * MAXNÂ
# Stores count_of_primescount_of_primes = [0] * MAXNÂ
# Function to generate primes# using Sieve of Eratosthenesdef 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 factorsdef numberOfWays(N):Â Â Â Â Â Â Â count = count_of_primes[N] - 1Â Â Â Â mod = 1000000007Â Â Â Â answer = power(2, count, mod)Â
    if N == 1:        answer = 0Â
    print(answer)Â
# Driver Codeif __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 Nstatic int MAXN = 1000000;Â
// Stores at each indices if// given number is prime or notstatic int[] is_prime;Â
// Stores count_of_primesstatic int[] count_of_primes;Â
// Function to generate primes// using Sieve of Eratosthenesstatic 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[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 factorsstatic 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 Codepublic static void Main(){         // Calling sieve function    sieve();Â
    // Given N    int N = 7;Â
    // Function call    numberOfWays(N);}}Â
// This code is contributed by akhilsaini |
Javascript
<script>Â
// Javascript Program for the above approachÂ
// Maximum value of Nvar MAXN = 1000000Â
// Stores at each indices if// given number is prime or notvar is_prime = Array(MAXN).fill(0);Â
// Stores count_of_primesvar count_of_primes = Array(MAXN).fill(0);Â
// Function to generate primes// using Sieve of Eratosthenesfunction sieve(){Â Â Â Â for (var i = 3; i < MAXN; i += 2) {Â
        // Assume all odds are primes        is_prime[i] = 1;    }Â
    for (var i = 3; i * i < MAXN; i += 2) {Â
        // If a prime is encountered        if (is_prime[i])Â
            for (var j = i * i; j < MAXN;                 j += i) {Â
                // Mark all its multiples                // as non-prime                is_prime[j] = 0;            }    }Â
    is_prime[2] = 1;Â
    // Count primes <= MAXN    for (var 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)function power(x, y, p){Â Â Â Â var 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 factorsfunction numberOfWays(N){    var count        = count_of_primes[N] - 1;    var mod = 1000000007;    var answer        = power(2, count, mod);Â
    if (N == 1)        answer = 0;Â
    document.write( answer);}Â
// Driver Code// Calling sieve functionsieve();// Given Nvar N = 7;// Function callnumberOfWays(N);Â
</script> |
8
Â
Time Complexity: O(log(log(N)) + log(N))
Auxiliary Space: O(N)
Â
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!
