Given an integer N, and an integer K, the task is to count the number of distinct ways to represent the number N as a sum of K unique primes.
Note: Distinct means, let N = 7 and K = 2, then the only way can be {2,5}, because {5,2} is same as {2,5}. So only 1 way.
Examples:
Input: N = 10, K = 2 Output: 1 Explanation: The only way is {3, 7} or {7, 3} Input: N = 100, K = 5 Output: 55
Approach: The problem can be solved using Dynamic Programming and Sieve of Eratosthenes.
- Let dp[i][j][sum] be our 3D DP array, which stores the number of distinct ways to form a sum using j number of primes where the last index of prime selected is i in the prime vector.
- The prime numbers can be efficiently computed using Sieve of Eratosthenes. So, we can get a check of prime in O(1) time.
- Recurrence:
We can either include this current prime to our sum, or we can exclude it.
dp[i][j][sum] = solve(i+1, j+1, sum+prime[i]) + solve(i+1, j, sum)
Below is the implementation of the above approach :
// C++ program to count the Number // of distinct ways to represent // a number as K different primes #include <bits/stdc++.h> using namespace std;
// Prime vector vector< int > prime;
// Sieve array of prime bool isprime[1000];
// DP array int dp[200][20][1000];
void sieve()
{ // Initialise all numbers
// as prime
memset (isprime, true ,
sizeof (isprime));
// Sieve of Eratosthenes.
for ( int i = 2; i * i <= 1000;
i++)
{
if (isprime[i])
{
for ( int j = i * i;
j <= 1000; j += i)
{
isprime[j] = false ;
}
}
}
// Push all the primes into
// prime vector
for ( int i = 2; i <= 1000; i++)
{
if (isprime[i])
{
prime.push_back(i);
}
}
} // Function to get the number of // distinct ways to get sum // as K different primes int CountWays( int i, int j, int sum,
int n, int k)
{ // If index went out of prime
// array size or the sum became
// larger than n return 0
if (i > prime.size() || sum > n)
{
return 0;
}
// If sum becomes equal to n and
// j becomes exactly equal to k.
// Return 1, else if j is still
// not equal to k, return 0
if (sum == n) {
if (j == k) {
return 1;
}
return 0;
}
// If sum!=n and still j as
// exceeded, return 0
if (j == k)
return 0;
// If that state is already
// calculated, return directly
// the ans
if (dp[i][j][sum])
return dp[i][j][sum];
int inc = 0, exc = 0;
// Include the current prime
inc = CountWays(i + 1, j + 1,
sum + prime[i],
n, k);
// Exclude the current prime
exc = CountWays(i + 1, j, sum,
n, k);
// Return by memoizing the ans
return dp[i][j][sum] = inc + exc;
} // Driver code int main()
{ // Precompute primes by sieve
sieve();
int N = 100, K = 5;
cout << CountWays(0, 0, 0, N, K);
} |
// Java program to count the number // of distinct ways to represent // a number as K different primes import java.io.*;
import java.util.*;
class GFG{
// Prime vector static ArrayList<Integer> prime = new ArrayList<Integer>();
// Sieve array of prime static boolean [] isprime = new boolean [ 1000 ];
// DP array static int [][][] dp = new int [ 200 ][ 20 ][ 1000 ];
static void sieve()
{ // Initialise all numbers
// as prime
for ( int i = 0 ; i < 1000 ; i++)
isprime[i] = true ;
// Sieve of Eratosthenes.
for ( int i = 2 ; i * i < 1000 ; i++)
{
if (isprime[i])
{
for ( int j = i * i;
j < 1000 ; j += i)
{
isprime[j] = false ;
}
}
}
// Push all the primes into
// prime vector
for ( int i = 2 ; i < 1000 ; i++)
{
if (isprime[i])
{
prime.add(i);
}
}
} // Function to get the number of // distinct ways to get sum // as K different primes static int CountWays( int i, int j, int sum,
int n, int k)
{ // If index went out of prime
// array size or the sum became
// larger than n return 0
if (i >= prime.size() - 1 || sum > n)
{
return 0 ;
}
// If sum becomes equal to n and
// j becomes exactly equal to k.
// Return 1, else if j is still
// not equal to k, return 0
if (sum == n)
{
if (j == k)
{
return 1 ;
}
return 0 ;
}
// If sum!=n and still j as
// exceeded, return 0
if (j == k)
return 0 ;
// If that state is already
// calculated, return directly
// the ans
if (dp[i][j][sum] != 0 )
return dp[i][j][sum];
int inc = 0 , exc = 0 ;
// Include the current prime
inc = CountWays(i + 1 , j + 1 ,
sum + prime.get(i),
n, k);
// Exclude the current prime
exc = CountWays(i + 1 , j, sum, n, k);
// Return by memoizing the ans
return dp[i][j][sum] = inc + exc;
} // Driver code public static void main(String[] args)
{ // Precompute primes by sieve
sieve();
int N = 100 , K = 5 ;
System.out.println(CountWays( 0 , 0 , 0 , N, K));
} } // This code is contributed by akhilsaini |
# Python3 program to count the number # of distinct ways to represent # a number as K different primes # Prime list prime = []
# Sieve array of prime isprime = [ True ] * 1000
# DP array dp = [[[ '0' for col in range ( 200 )]
for col in range ( 20 )]
for row in range ( 1000 )]
def sieve():
# Sieve of Eratosthenes.
for i in range ( 2 , 1000 ):
if (isprime[i]):
for j in range (i * i, 1000 , i):
isprime[j] = False
# Push all the primes into
# prime vector
for i in range ( 2 , 1000 ):
if (isprime[i]):
prime.append(i)
# Function to get the number of # distinct ways to get sum # as K different primes def CountWays(i, j, sums, n, k):
# If index went out of prime
# array size or the sum became
# larger than n return 0
if (i > = len (prime) or sums > n):
return 0
# If sum becomes equal to n and
# j becomes exactly equal to k.
# Return 1, else if j is still
# not equal to k, return 0
if (sums = = n):
if (j = = k):
return 1
return 0
# If sum!=n and still j as
# exceeded, return 0
if j = = k:
return 0
# If that state is already
# calculated, return directly
# the ans
if dp[i][j][sums] = = 0 :
return dp[i][j][sums]
inc = 0
exc = 0
# Include the current prime
inc = CountWays(i + 1 , j + 1 ,
sums + prime[i],
n, k)
# Exclude the current prime
exc = CountWays(i + 1 , j, sums, n, k)
# Return by memoizing the ans
dp[i][j][sums] = inc + exc
return dp[i][j][sums]
# Driver code if __name__ = = "__main__" :
# Precompute primes by sieve
sieve()
N = 100
K = 5
print (CountWays( 0 , 0 , 0 , N, K))
# This code is contributed by akhilsaini |
// C# program to count the number // of distinct ways to represent // a number as K different primes using System;
using System.Collections.Generic;
class GFG{
// Prime vector static List< int > prime = new List< int >();
// Sieve array of prime static bool [] isprime = new bool [1000];
// DP array static int [, , ] dp = new int [200, 20, 1000];
static void sieve()
{ // Initialise all numbers
// as prime
for ( int i = 0; i < 1000; i++)
isprime[i] = true ;
// Sieve of Eratosthenes.
for ( int i = 2; i * i < 1000; i++)
{
if (isprime[i])
{
for ( int j = i * i;
j < 1000; j += i)
{
isprime[j] = false ;
}
}
}
// Push all the primes into
// prime vector
for ( int i = 2; i < 1000; i++)
{
if (isprime[i])
{
prime.Add(i);
}
}
} // Function to get the number of // distinct ways to get sum // as K different primes static int CountWays( int i, int j, int sum,
int n, int k)
{ // If index went out of prime
// array size or the sum became
// larger than n return 0
if (i >= prime.Count - 1 || sum > n)
{
return 0;
}
// If sum becomes equal to n and
// j becomes exactly equal to k.
// Return 1, else if j is still
// not equal to k, return 0
if (sum == n)
{
if (j == k)
{
return 1;
}
return 0;
}
// If sum!=n and still j as
// exceeded, return 0
if (j == k)
return 0;
// If that state is already
// calculated, return directly
// the ans
if (dp[i, j, sum] != 0)
return dp[i, j, sum];
int inc = 0, exc = 0;
// Include the current prime
inc = CountWays(i + 1, j + 1,
sum + prime[i], n, k);
// Exclude the current prime
exc = CountWays(i + 1, j, sum, n, k);
// Return by memoizing the ans
return dp[i, j, sum] = inc + exc;
} // Driver code static public void Main()
{ // Precompute primes by sieve
sieve();
int N = 100, K = 5;
Console.WriteLine(CountWays(0, 0, 0, N, K));
} } // This code is contributed by akhilsaini |
<script> // Javascript program to count the Number // of distinct ways to represent // a number as K different primes // Prime vector var prime = [];
// Sieve array of prime var isprime = Array(1000).fill( true );
// DP array var dp = Array.from(Array(200), ()=>Array(20));
for ( var i =0; i<200; i++)
for ( var j =0; j<20; j++)
dp[i][j] = new Array(1000).fill(0);
function sieve()
{ // Initialise all numbers
// as prime
// Sieve of Eratosthenes.
for ( var i = 2; i * i <= 1000;
i++)
{
if (isprime[i])
{
for ( var j = i * i;
j <= 1000; j += i)
{
isprime[j] = false ;
}
}
}
// Push all the primes into
// prime vector
for ( var i = 2; i <= 1000; i++)
{
if (isprime[i])
{
prime.push(i);
}
}
} // Function to get the number of // distinct ways to get sum // as K different primes function CountWays(i, j, sum, n, k)
{ // If index went out of prime
// array size or the sum became
// larger than n return 0
if (i > prime.length || sum > n)
{
return 0;
}
// If sum becomes equal to n and
// j becomes exactly equal to k.
// Return 1, else if j is still
// not equal to k, return 0
if (sum == n) {
if (j == k) {
return 1;
}
return 0;
}
// If sum!=n and still j as
// exceeded, return 0
if (j == k)
return 0;
// If that state is already
// calculated, return directly
// the ans
if (dp[i][j][sum])
return dp[i][j][sum];
var inc = 0, exc = 0;
// Include the current prime
inc = CountWays(i + 1, j + 1,
sum + prime[i],
n, k);
// Exclude the current prime
exc = CountWays(i + 1, j, sum,
n, k);
// Return by memoizing the ans
return dp[i][j][sum] = inc + exc;
} // Driver code // Precompute primes by sieve sieve(); var N = 100, K = 5;
document.write( CountWays(0, 0, 0, N, K)); </script> |
55
Time Complexity: O(N*K).
Auxiliary Space: O(20*200*1000).