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 not int is_prime[MAXN] = { 0 }; Â
// Stores count_of_primes int count_of_primes[MAXN] = { 0 }; Â
// Function to generate primes // using Sieve of Eratosthenes 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[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 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 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 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 Eratosthenes 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 Eratosthenes 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[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; Â Â Â Â 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 |
Javascript
<script> Â
// Javascript Program for the above approach Â
// Maximum value of N var MAXN = 1000000 Â
// Stores at each indices if // given number is prime or not var is_prime = Array(MAXN).fill(0); Â
// Stores count_of_primes var count_of_primes = Array(MAXN).fill(0); Â
// Function to generate primes // using Sieve of Eratosthenes function 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 factors function 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 function sieve(); // Given N var N = 7; // Function call numberOfWays(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!