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 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[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 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[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 |
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.