Open In App

Count of N digit numbers which contains all single digit primes

Last Updated : 17 Aug, 2021
Improve
Improve
Like Article
Like
Save
Share
Report

Given a positive integer N, the task is to count the number of N-digit numbers which contain all single digit primes.

Examples:

Input: N = 4
Output: 24
Explanation: The number of single digit primes is 4 i.e.{2, 3, 5, 7}. Hence number of ways to arrange 4 numbers in 4 places is 4! = 24.

Input: N = 5
Output: 936

Naive Approach: The simplest approach to solve the given problem is to generate all possible N-digit numbers and count those numbers which contain all single digit prime numbers. After checking for all the numbers, print the value of the count as the resultant total count of numbers.

Time Complexity: O(N *10N)
Auxiliary Space: O(1)

Efficient Approach: The above approach can also be optimized by using Dynamic Programming because it has overlapping subproblems and optimal substructure. The subproblems can be stored in dp[][] table using memoization where dp[index][mask] stores the answer from the indexth position till the end, where mask is used to store the count of distinct primes included till now. Follow the steps below to solve the problem:

  • Initialize a global multidimensional array dp[100][1<<4] with all values as -1 that stores the result of each recursive call.
  • Index all the single digit prime numbers in ascending order using a HashMap.
  • Define a recursive function, say countOfNumbers(index, mask, N) by performing the following steps.
    • If the value of a index is equal to (N + 1),  
      • Count the number of distinct single digit primes included by finding the count of set bits in the mask.
      • If the count is equal to 4, return 1 as a valid N-digit number has been formed.
      • Otherwise return 0.
    • If the result of the state dp[index][mask] is already computed, return this value dp[index][mask].
    • If the current index is 1, then any digit from [1- 9] can be placed and if N = 1, then 0 can be placed as well.
    • For all other index, any digit from [0-9] can be placed.
    • If the current digit placed is a prime number, then set the index of the prime number to 1 in the bitmask.
    • After making a valid placement, recursively call the countOfNumbers function for (index + 1).
    • Return the sum of all possible valid placements of digits as the answer.
  • Print the value returned by the function countOfNumbers(1, 0, N) as the result.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Stores the dp-states
int dp[100][1 << 4];
 
// Stores the index of prime numbers
map<int, int> primeIndex;
 
int countOfNumbers(int index, int mask, int N)
{
    // If index = N+1
    if (index == N + 1) {
 
        // Find count of distinct
        // prime numbers by counting
        // number of set bits.
        int countOfPrimes = __builtin_popcount(mask);
 
        // If count of distinct
        // prime numbers is equal to 4
        // return 1.
        if (countOfPrimes == 4) {
            return 1;
        }
        return 0;
    }
 
    int& val = dp[index][mask];
 
    // If the state has
    // already been computed
    if (val != -1) {
        return val;
    }
 
    val = 0;
 
    // If current position is 1,
    // then any digit from [1-9] can be placed.
    // If N = 1, 0 can be also placed.
    if (index == 1) {
        for (int digit = (N == 1 ? 0 : 1); digit <= 9;
             ++digit) {
 
            // If the digit is a prime number,
            // set the index of the
            // digit to 1 in the bitmask.
            if (primeIndex.find(digit)
                != primeIndex.end()) {
                val += countOfNumbers(
                    index + 1,
                    mask | (1 << primeIndex[digit]), N);
            }
 
            else {
                val += countOfNumbers(index + 1, mask, N);
            }
        }
    }
 
    // For remaining positions,
    // any digit from [0-9] can be placed
    else {
        for (int digit = 0; digit <= 9; ++digit) {
 
            // If the digit is a prime number,
            // set the index of the
            // digit to 1 in the bitmask.
            if (primeIndex.find(digit)
                != primeIndex.end()) {
                val += countOfNumbers(
                    index + 1,
                    mask | (1 << primeIndex[digit]), N);
            }
 
            else {
                val += countOfNumbers(index + 1, mask, N);
            }
        }
    }
 
    // Return the answer.
    return val;
}
 
// Driver Code
int main()
{
    // Initializing dp array with -1.
    memset(dp, -1, sizeof dp);
 
    // Indexing prime numbers in
    // ascending order
    primeIndex[2] = 0;
    primeIndex[3] = 1;
    primeIndex[5] = 2;
    primeIndex[7] = 3;
 
    // Given Input
    int N = 4;
 
    // Function call.
    cout << countOfNumbers(1, 0, N);
 
    return 0;
}


Java




// Java program for the above approach
import java.io.*;
import java.util.*;
 
class GFG{
 
public static int[][] dp = new int[100][(1 << 4)];
 
// Stores the index of prime numbers
public static HashMap<Integer,
                      Integer> primeIndex = new HashMap<>();
 
public static int countSetBits(int n)
{
    int count = 0;
     
    while (n > 0)
    {
        count += n & 1;
        n >>= 1;
    }
    return count;
}
 
public static int countOfNumbers(int index, int mask,
                                 int N)
{
     
    // If index = N+1
    if (index == N + 1)
    {
         
        // Find count of distinct
        // prime numbers by counting
        // number of set bits.
        int countOfPrimes = countSetBits(mask);
 
        // If count of distinct
        // prime numbers is equal to 4
        // return 1.
        if (countOfPrimes == 4)
        {
            return 1;
        }
        return 0;
    }
 
    int val = dp[index][mask];
 
    // If the state has
    // already been computed
    if (val != -1)
    {
        return val;
    }
 
    val = 0;
 
    // If current position is 1, then any
    // digit from [1-9] can be placed.
    // If N = 1, 0 can be also placed.
    if (index == 1)
    {
        for(int digit = (N == 1 ? 0 : 1);
                digit <= 9; ++digit)
        {
             
            // If the digit is a prime number,
            // set the index of the digit to 1
            // in the bitmask.
            if (primeIndex.containsKey(digit))
            {
                int newMask = mask | (1 << primeIndex.get(digit));
                val += countOfNumbers(index + 1,
                                      newMask, N);
            }
 
            else
            {
                val += countOfNumbers(index + 1, mask, N);
            }
        }
    }
 
    // For remaining positions,
    // any digit from [0-9] can be placed
    else
    {
        for(int digit = 0; digit <= 9; ++digit)
        {
             
            // If the digit is a prime number,
            // set the index of the digit to 1
            // in the bitmask.
            if (primeIndex.containsKey(digit))
            {
                int newMask = mask | (1 << primeIndex.get(digit));
                val += countOfNumbers(index + 1, newMask, N);
            }
            else
            {
                val += countOfNumbers(index + 1, mask, N);
            }
        }
    }
 
    // Return the answer.
    return val;
}
 
// Driver Code
public static void main(String[] args)
{
     
    // Initializing dp array with -1.
    for(int i = 0; i < 100; i++)
    {
        for(int j = 0; j < (1 << 4); j++)
        {
            dp[i][j] = -1;
        }
    }
 
    // Indexing prime numbers in
    // ascending order
    primeIndex.put(2, 0);
    primeIndex.put(3, 1);
    primeIndex.put(5, 2);
    primeIndex.put(7, 3);
 
    // Given Input
    int N = 4;
 
    // Function call
    System.out.println(countOfNumbers(1, 0, N));
}
}
 
// This code is contributed by maddler


Python3




# Python3 program for the above approach
 
# Stores the dp-states
dp = [[-1 for i in range(1<<4)] for j in range(100)]
 
# Stores the index of prime numbers
primeIndex = {}
 
def  countSetBits(n):
    count = 0
    while (n):
        count += n & 1
        n >>= 1
    return count
 
def countOfNumbers(index, mask, N):
    # If index = N+1
    if (index == N + 1):
 
        # Find count of distinct
        # prime numbers by counting
        # number of set bits.
        countOfPrimes = countSetBits(mask);
 
        # If count of distinct
        # prime numbers is equal to 4
        # return 1.
        if (countOfPrimes == 4):
            return 1
        return 0
 
    val = dp[index][mask]
 
    # If the state has
    # already been computed
    if (val != -1):
        return val
 
    val = 0
 
    # If current position is 1,
    # then any digit from [1-9] can be placed.
    # If N = 1, 0 can be also placed.
    if (index == 1):
        digit = 0 if N == 1 else 1
        while(digit <= 9):
            # If the digit is a prime number,
            # set the index of the
            # digit to 1 in the bitmask.
            if (digit in primeIndex):
                val += countOfNumbers(index + 1,mask | (1 << primeIndex[digit]), N)
 
            else:
                val += countOfNumbers(index + 1, mask, N)
 
            digit += 1
 
    # For remaining positions,
    # any digit from [0-9] can be placed
    else:
        for digit in range(10):
            # If the digit is a prime number,
            # set the index of the
            # digit to 1 in the bitmask.
            if (digit in primeIndex):
                val += countOfNumbers(index + 1,mask | (1 << primeIndex[digit]), N)
 
            else:
                val += countOfNumbers(index + 1, mask, N)
 
    # Return the answer.
    return val
 
# Driver Code
if __name__ == '__main__':
    # Initializing dp array with -1.
    # Indexing prime numbers in
    # ascending order
    primeIndex[2] = 0
    primeIndex[3] = 1
    primeIndex[5] = 2
    primeIndex[7] = 3
 
    # Given Input
    N = 4
 
    # Function call.
    print(countOfNumbers(1, 0, N))
     
    # This code is contributed by ipg2016107.


C#




// C# program for the above approach
using System;
using System.Collections.Generic;
 
public class GFG
{
 
public static int[,] dp = new int[100,(1 << 4)];
 
// Stores the index of prime numbers
public static Dictionary<int,int> primeIndex = new Dictionary<int,int>();
 
public static int countSetBits(int n)
{
    int count = 0;
     
    while (n > 0)
    {
        count += n & 1;
        n >>= 1;
    }
    return count;
}
 
public static int countOfNumbers(int index, int mask,
                                 int N)
{
     
    // If index = N+1
    if (index == N + 1)
    {
         
        // Find count of distinct
        // prime numbers by counting
        // number of set bits.
        int countOfPrimes = countSetBits(mask);
 
        // If count of distinct
        // prime numbers is equal to 4
        // return 1.
        if (countOfPrimes == 4)
        {
            return 1;
        }
        return 0;
    }
 
    int val = dp[index,mask];
 
    // If the state has
    // already been computed
    if (val != -1)
    {
        return val;
    }
 
    val = 0;
 
    // If current position is 1, then any
    // digit from [1-9] can be placed.
    // If N = 1, 0 can be also placed.
    if (index == 1)
    {
        for(int digit = (N == 1 ? 0 : 1);
                digit <= 9; ++digit)
        {
             
            // If the digit is a prime number,
            // set the index of the digit to 1
            // in the bitmask.
            if (primeIndex.ContainsKey(digit))
            {
                int newMask = mask | (1 << primeIndex[digit]);
                val += countOfNumbers(index + 1,
                                      newMask, N);
            }
 
            else
            {
                val += countOfNumbers(index + 1, mask, N);
            }
        }
    }
 
    // For remaining positions,
    // any digit from [0-9] can be placed
    else
    {
        for(int digit = 0; digit <= 9; ++digit)
        {
             
            // If the digit is a prime number,
            // set the index of the digit to 1
            // in the bitmask.
            if (primeIndex.ContainsKey(digit))
            {
                int newMask = mask | (1 << primeIndex[digit]);
                val += countOfNumbers(index + 1, newMask, N);
            }
            else
            {
                val += countOfNumbers(index + 1, mask, N);
            }
        }
    }
 
    // Return the answer.
    return val;
}
 
// Driver Code
public static void Main(String[] args)
{
     
    // Initializing dp array with -1.
    for(int i = 0; i < 100; i++)
    {
        for(int j = 0; j < (1 << 4); j++)
        {
            dp[i,j] = -1;
        }
    }
 
    // Indexing prime numbers in
    // ascending order
    primeIndex.Add(2, 0);
    primeIndex.Add(3, 1);
    primeIndex.Add(5, 2);
    primeIndex.Add(7, 3);
 
    // Given Input
    int N = 4;
 
    // Function call
    Console.WriteLine(countOfNumbers(1, 0, N));
}
}
 
// This code is contributed by shikhasingrajput


Javascript




<script>
// Javascript program for the above approach
 
let dp = new Array(100).fill(0).map(() => new Array(1 << 4));
 
// Stores the index of prime numbers
let primeIndex = new Map();
 
function countSetBits(n) {
  let count = 0;
 
  while (n > 0) {
    count += n & 1;
    n >>= 1;
  }
  return count;
}
 
function countOfNumbers(index, mask, N) {
  // If index = N+1
  if (index == N + 1) {
    // Find count of distinct
    // prime numbers by counting
    // number of set bits.
    let countOfPrimes = countSetBits(mask);
 
    // If count of distinct
    // prime numbers is equal to 4
    // return 1.
    if (countOfPrimes == 4) {
      return 1;
    }
    return 0;
  }
 
  let val = dp[index][mask];
 
  // If the state has
  // already been computed
  if (val != -1) {
    return val;
  }
 
  val = 0;
 
  // If current position is 1, then any
  // digit from [1-9] can be placed.
  // If N = 1, 0 can be also placed.
  if (index == 1) {
    for (let digit = N == 1 ? 0 : 1; digit <= 9; ++digit) {
      // If the digit is a prime number,
      // set the index of the digit to 1
      // in the bitmask.
      if (primeIndex.has(digit)) {
        let newMask = mask | (1 << primeIndex.get(digit));
        val += countOfNumbers(index + 1, newMask, N);
      } else {
        val += countOfNumbers(index + 1, mask, N);
      }
    }
  }
 
  // For remaining positions,
  // any digit from [0-9] can be placed
  else {
    for (let digit = 0; digit <= 9; ++digit) {
      // If the digit is a prime number,
      // set the index of the digit to 1
      // in the bitmask.
      if (primeIndex.has(digit)) {
        let newMask = mask | (1 << primeIndex.get(digit));
        val += countOfNumbers(index + 1, newMask, N);
      } else {
        val += countOfNumbers(index + 1, mask, N);
      }
    }
  }
 
  // Return the answer.
  return val;
}
 
// Driver Code
 
// Initializing dp array with -1.
for (let i = 0; i < 100; i++) {
  for (let j = 0; j < 1 << 4; j++) {
    dp[i][j] = -1;
  }
}
 
// Indexing prime numbers in
// ascending order
primeIndex.set(2, 0);
primeIndex.set(3, 1);
primeIndex.set(5, 2);
primeIndex.set(7, 3);
 
// Given Input
let N = 4;
 
// Function call
document.write(countOfNumbers(1, 0, N));
 
// This code is contributed by gfgking
 
</script>


Output

24

Time Complexity: O(N *10 * 24)
Auxiliary Space: O(N * 24



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads