Count numbers in a given range having prime and non-prime digits at prime and non-prime positions respectively
Given two integers L and R, the task is to find the count of numbers in the range [L, R] having prime digits at prime positions and non-prime digits at non-prime positions.
Examples:
Input: L = 5, R = 22 Â
Output: 7
Explanation: The numbers 6, 8, 9, 12, 13, 15, and 17 have prime digits at prime positions and non-prime digits at non-prime positions.Input: L = 20, R = 29
Output: 0
Explanation: There are no numbers which have prime digits at prime positions and non-prime digits at non-prime positions.
Naive Approach: The simplest approach to solve the problem is to iterate over the range [L, R]. For every ith number check if the digits of the number is prime at prime positions and non-prime at non-prime positions or not. If found to be true, then increment the count. Finally, print the count obtained.Â
Time Complexity: O(R – L + 1) * sqrt(R) * log10(R)Â
Auxiliary Space: O(1)
Efficient Approach: To optimize the above approach, the idea is to use Digit DP. Following are the recurrence relation between the dynamic programming states:
If i is a prime at prime digits or non-prime at non-prime digits, then x = 1Â
Â
pos: Stores position of digitsÂ
prime: Check if prime digits are present at prime positions and non-prime digits at non-prime positions are present or not.Â
st: check if a number contains any leading 0.Â
end: Maximum possible digits at current positionÂ
Follow the steps below to solve the problem:
- Initialize a 4D array, say dp[pos][st][tight][prime].
- Compute the value of dp[pos][st][tight][prime] for the number R using memorization, say cntR.
- Compute the value of dp[pos][st][tight][prime] for the number L – 1 using memorization, say cntL.
- Finally, print the value of (cntR – cntL).
Below is the implementation of the above approach:
C++14
// C++ program for the above approach Â
#include <bits/stdc++.h> using namespace std; Â
// Store digits of a number vector< long long int > num; Â
// Store overlapping subproblems long long int dp[19][2][2][19]; Â
// Function to check if a // number is prime or not bool isPrime( long long int n) { Â
    // If n is less than     // or equal to 1     if (n <= 1)         return false ; Â
    // If n is less than     // or equal to 3     if (n <= 3)         return true ; Â
    // If n is a multiple of 2 or 3     if (n % 2 == 0 || n % 3 == 0)         return false ; Â
    // Iterate over the range [5, n]     for ( long long int i = 5; i * i <= n;          i = i + 6) { Â
        // If n is a multiple of i or (i + 2)         if (n % i == 0 || n % (i + 2) == 0)             return false ;     } Â
    return true ; } Â
// Function to count the required // numbers from the given range long long cntNum( long long pos, long long st, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â long long tight, long long prime) { Â
    // Base Case     if (pos == num.size())         return 1; Â
    // If the subproblems already computed     if (dp[pos][st][tight][prime] != -1)         return dp[pos][st][tight][prime]; Â
    long long int res = 0; Â
    // Stores maximum possible     // at current digits     long long end = (tight == 0) ? num[pos] : 9; Â
    // Iterate over all possible digits     // at current position     for ( long long i = 0; i <= end; i++) { Â
        // Check if i is the maximum possible         // digit at current position or not         long long ntight = (i < end) ? 1 : tight; Â
        // Check if a number contains         // leading 0s or not         long long int nzero = (i != 0) ? 1 : st; Â
        // If number has only leading zeros         // and digit is non-zero         if ((nzero == 1) && isPrime(i) && isPrime(prime)) { Â
            // Prime digits at prime positions             res += cntNum(pos + 1, nzero,                           ntight, prime + 1);         } Â
        if ((nzero == 1) && !isPrime(i) && !isPrime(prime)) { Â
            // Non-prime digits at             // non-prime positions             res += cntNum(pos + 1, nzero,                           ntight, prime + 1);         } Â
        // If the number has only leading zeros         // and i is zero,         if (nzero == 0)             res += cntNum(pos + 1, nzero,                           ntight, prime);     }     return dp[pos][st][tight][prime] = res; } Â
// Function to find count of numbers in // range [0, b] whose digits are prime // at prime and non-prime at non-prime pos long long int cntZeroRange( long long int b) { Â
    num.clear(); Â
    // Insert digits of a number, b     while (b > 0) {         num.push_back(b % 10);         b /= 10;     } Â
    // Reversing the digits in num     reverse(num.begin(), num.end()); Â
    // Initializing dp with -1     memset (dp, -1, sizeof (dp)); Â
    long long int res = cntNum(0, 0, 0, 1); Â
    // Returning the value     return res; } Â
// Driver Code int main() { Â
    // Given range, [L, R]     long long int L = 5, R = 22; Â
    // Function Call     long long int res         = cntZeroRange(R) - cntZeroRange(L - 1); Â
    // Print answer     cout << res << endl;     return 0; } |
Java
// Java program for the above approach import java.util.*; class GFG { Â
// Store digits of a number static Vector<Integer> num = new Vector<>(); Â
// Store overlapping subproblems static int [][][][]dp = new int [ 19 ][ 2 ][ 2 ][ 19 ]; Â
// Function to check if a // number is prime or not static boolean isPrime( int n) { Â
    // If n is less than     // or equal to 1     if (n <= 1 )         return false ; Â
    // If n is less than     // or equal to 3     if (n <= 3 )         return true ; Â
    // If n is a multiple of 2 or 3     if (n % 2 == 0 || n % 3 == 0 )         return false ; Â
    // Iterate over the range [5, n]     for ( int i = 5 ; i * i <= n;          i = i + 6 ) { Â
        // If n is a multiple of i or (i + 2)         if (n % i == 0 || n % (i + 2 ) == 0 )             return false ;     }     return true ; } Â
// Function to count the required // numbers from the given range static int cntNum( int pos, int st, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â int tight, int prime) { Â
    // Base Case     if (pos == num.size())         return 1 ; Â
    // If the subproblems already computed     if (dp[pos][st][tight][prime] != - 1 )         return dp[pos][st][tight][prime];     int res = 0 ; Â
    // Stores maximum possible     // at current digits     int end = (tight == 0 ) ? num.get(pos) : 9 ; Â
    // Iterate over all possible digits     // at current position     for ( int i = 0 ; i <= end; i++)     { Â
        // Check if i is the maximum possible         // digit at current position or not         int ntight = (i < end) ? 1 : tight; Â
        // Check if a number contains         // leading 0s or not         int nzero = (i != 0 ) ? 1 : st; Â
        // If number has only leading zeros         // and digit is non-zero         if ((nzero == 1 ) && isPrime(i) && isPrime(prime)) { Â
            // Prime digits at prime positions             res += cntNum(pos + 1 , nzero,                           ntight, prime + 1 );         } Â
        if ((nzero == 1 ) && !isPrime(i) && !isPrime(prime)) { Â
            // Non-prime digits at             // non-prime positions             res += cntNum(pos + 1 , nzero,                           ntight, prime + 1 );         } Â
        // If the number has only leading zeros         // and i is zero,         if (nzero == 0 )             res += cntNum(pos + 1 , nzero,                           ntight, prime);     }     return dp[pos][st][tight][prime] = res; } Â
// Function to find count of numbers in // range [0, b] whose digits are prime // at prime and non-prime at non-prime pos static int cntZeroRange( int b) { Â
    num.clear(); Â
    // Insert digits of a number, b     while (b > 0 ) {         num.add(b % 10 );         b /= 10 ;     } Â
    // Reversing the digits in num     Collections.reverse(num); Â
    // Initializing dp with -1     for ( int i = 0 ; i < 19 ; i++)          for ( int j = 0 ; j < 2 ; j++)              for ( int k = 0 ; k < 2 ; k++)                  for ( int l = 0 ; l < 19 ; l++)                      dp[i][j][k][l] = - 1 ; Â
    int res = cntNum( 0 , 0 , 0 , 1 ); Â
    // Returning the value     return res; } Â
// Driver Code public static void main(String[] args) { Â
    // Given range, [L, R]     int L = 5 , R = 22 ; Â
    // Function Call     int res         = cntZeroRange(R) - cntZeroRange(L - 1 ); Â
    // Print answer     System.out.print(res + "\n" ); } } Â
// This code is contributed by 29AjayKumar |
Python3
# Python3 program for the above approach from math import ceil, sqrt Â
# Function to check if a # number is prime or not def isPrime(n):          # If n is less than     # or equal to 1     if (n < = 1 ):         return False Â
    # If n is less than     # or equal to 3     if (n < = 3 ):         return True Â
    # If n is a multiple of 2 or 3     if (n % 2 = = 0 or n % 3 = = 0 ):         return False Â
    # Iterate over the range [5, n]     for i in range ( 5 , ceil(sqrt(n)), 6 ):                  # If n is a multiple of i or (i + 2)         if (n % i = = 0 or n % (i + 2 ) = = 0 ):             return False Â
    return True Â
# Function to count the required # numbers from the given range def cntNum(pos, st, tight, prime):          global dp, num          if (pos = = len (num)):         return 1 Â
    # If the subproblems already computed     if (dp[pos][st][tight][prime] ! = - 1 ):         return dp[pos][st][tight][prime] Â
    res = 0 Â
    # Stores maximum possible     # at current digits     end = num[pos] if (tight = = 0 ) else  9 Â
    # Iterate over all possible digits     # at current position     for i in range (end + 1 ):                  # Check if i is the maximum possible         # digit at current position or not         ntight = 1 if (i < end) else tight Â
        # Check if a number contains         # leading 0s or not         nzero = 1 if (i ! = 0 ) else st Â
        # If number has only leading zeros         # and digit is non-zero         if ((nzero = = 1 ) and isPrime(i) and                              isPrime(prime)):                                               # Prime digits at prime positions             res + = cntNum(pos + 1 , nzero, ntight,                         prime + 1 ) Â
        if ((nzero = = 1 ) and isPrime(i) = = False and                          isPrime(prime) = = False ): Â
            # Non-prime digits at             # non-prime positions             res + = cntNum(pos + 1 , nzero, ntight,                         prime + 1 ) Â
        # If the number has only leading zeros         # and i is zero,         if (nzero = = 0 ):             res + = cntNum(pos + 1 , nzero,                           ntight, prime)                                dp[pos][st][tight][prime] = res          return dp[pos][st][tight][prime] Â
# Function to find count of numbers in # range [0, b] whose digits are prime # at prime and non-prime at non-prime pos def cntZeroRange(b): Â Â Â Â Â Â Â Â Â global num, dp Â
    num.clear()          while (b > 0 ):         num.append(b % 10 )         b / / = 10 Â
    # Reversing the digits in num     num = num[:: - 1 ] Â
    # print(num)     dp = [[[[ - 1 for i in range ( 19 )]                 for i in range ( 2 )]                 for i in range ( 2 )]                 for i in range ( 19 )] Â
    res = cntNum( 0 , 0 , 0 , 1 ) Â
    # Returning the value     return res Â
# Driver Code if __name__ = = '__main__' : Â
    dp = [[[[ - 1 for i in range ( 19 )]                 for i in range ( 2 )]                 for i in range ( 2 )]                 for i in range ( 19 )]     L, R, num = 5 , 22 , [] Â
    # Function Call     res = cntZeroRange(R) - cntZeroRange(L - 1 ) Â
    # Print answer     print (res) Â
# This code is contributed by mohit kumar 29 |
C#
// C# program for the above approach using System; using System.Collections.Generic; class GFG { Â
  // Store digits of a number   static List< int > num = new List< int >(); Â
  // Store overlapping subproblems   static int [, , , ] dp = new int [19, 2, 2, 19]; Â
  // Function to check if a   // number is prime or not   static bool isPrime( int n)   { Â
    // If n is less than     // or equal to 1     if (n <= 1)       return false ; Â
    // If n is less than     // or equal to 3     if (n <= 3)       return true ; Â
    // If n is a multiple of 2 or 3     if (n % 2 == 0 || n % 3 == 0)       return false ; Â
    // Iterate over the range [5, n]     for ( int i = 5; i * i <= n; i = i + 6) { Â
      // If n is a multiple of i or (i + 2)       if (n % i == 0 || n % (i + 2) == 0)         return false ;     }     return true ;   } Â
  // Function to count the required   // numbers from the given range   static int cntNum( int pos, int st, int tight, int prime)   { Â
    // Base Case     if (pos == num.Count)       return 1; Â
    // If the subproblems already computed     if (dp[pos, st, tight, prime] != -1)       return dp[pos, st, tight, prime];     int res = 0; Â
    // Stores maximum possible     // at current digits     int end = (tight == 0) ? num[pos] : 9; Â
    // Iterate over all possible digits     // at current position     for ( int i = 0; i <= end; i++) { Â
      // Check if i is the maximum possible       // digit at current position or not       int ntight = (i < end) ? 1 : tight; Â
      // Check if a number contains       // leading 0s or not       int nzero = (i != 0) ? 1 : st; Â
      // If number has only leading zeros       // and digit is non-zero       if ((nzero == 1) && isPrime(i)           && isPrime(prime)) { Â
        // Prime digits at prime positions         res += cntNum(pos + 1, nzero, ntight,                       prime + 1);       } Â
      if ((nzero == 1) && !isPrime(i)           && !isPrime(prime)) { Â
        // Non-prime digits at         // non-prime positions         res += cntNum(pos + 1, nzero, ntight,                       prime + 1);       } Â
      // If the number has only leading zeros       // and i is zero,       if (nzero == 0)         res += cntNum(pos + 1, nzero, ntight,                       prime);     }     return dp[pos, st, tight, prime] = res;   } Â
  // Function to find count of numbers in   // range [0, b] whose digits are prime   // at prime and non-prime at non-prime pos   static int cntZeroRange( int b)   { Â
    num.Clear(); Â
    // Insert digits of a number, b     while (b > 0) {       num.Add(b % 10);       b /= 10;     } Â
    // Reversing the digits in num     num.Reverse(); Â
    // Initializing dp with -1     for ( int i = 0; i < 19; i++)       for ( int j = 0; j < 2; j++)         for ( int k = 0; k < 2; k++)           for ( int l = 0; l < 19; l++)             dp[i, j, k, l] = -1; Â
    int res = cntNum(0, 0, 0, 1); Â
    // Returning the value     return res;   } Â
  // Driver Code   public static void Main( string [] args)   { Â
    // Given range, [L, R]     int L = 5, R = 22; Â
    // Function Call     int res = cntZeroRange(R) - cntZeroRange(L - 1); Â
    // Print answer     Console.WriteLine(res + "\n" );   } } Â
// This code is contributed by chitranayal. |
Javascript
<script> Â
// JavaScript program for the above approach Â
// Store digits of a number let num = []; Â
// Store overlapping subproblems let dp = new Array(19); Â
Â
// Function to check if a // number is prime or not function isPrime(n) {     // If n is less than     // or equal to 1     if (n <= 1)         return false ;       // If n is less than     // or equal to 3     if (n <= 3)         return true ;       // If n is a multiple of 2 or 3     if (n % 2 == 0 || n % 3 == 0)         return false ;       // Iterate over the range [5, n]     for (let i = 5; i * i <= n;          i = i + 6) {           // If n is a multiple of i or (i + 2)         if (n % i == 0 || n % (i + 2) == 0)             return false ;     }     return true ; } Â
// Function to count the required // numbers from the given range function cntNum(pos,st,tight,prime) {     // Base Case     if (pos == num.length)         return 1;       // If the subproblems already computed     if (dp[pos][st][tight][prime] != -1)         return dp[pos][st][tight][prime];     let res = 0;       // Stores maximum possible     // at current digits     let end = (tight == 0) ? num[pos] : 9;       // Iterate over all possible digits     // at current position     for (let i = 0; i <= end; i++)     {           // Check if i is the maximum possible         // digit at current position or not         let ntight = (i < end) ? 1 : tight;           // Check if a number contains         // leading 0s or not         let nzero = (i != 0) ? 1 : st;           // If number has only leading zeros         // and digit is non-zero         if ((nzero == 1) && isPrime(i) && isPrime(prime)) {               // Prime digits at prime positions             res += cntNum(pos + 1, nzero,                           ntight, prime + 1);         }           if ((nzero == 1) && !isPrime(i) && !isPrime(prime)) {               // Non-prime digits at             // non-prime positions             res += cntNum(pos + 1, nzero,                           ntight, prime + 1);         }           // If the number has only leading zeros         // and i is zero,         if (nzero == 0)             res += cntNum(pos + 1, nzero,                           ntight, prime);     }     return dp[pos][st][tight][prime] = res; } Â
// Function to find count of numbers in // range [0, b] whose digits are prime // at prime and non-prime at non-prime pos function cntZeroRange(b) {     num=[];       // Insert digits of a number, b     while (b > 0) {         num.push(b % 10);         b = Math.floor(b/10);     }       // Reversing the digits in num     num.reverse();      for (let i=0;i<19;i++) {     dp[i]= new Array(2);     for (let j=0;j<2;j++)     {         dp[i][j]= new Array(2);         for (let k=0;k<2;k++)         {             dp[i][j][k]= new Array(19);             for (let l=0;l<19;l++)             {                 dp[i][j][k][l]=-1;             }         }     } }               let res = cntNum(0, 0, 0, 1);       // Returning the value     return res; } Â
// Driver Code // Given range, [L, R] let L = 5, R = 22; Â
// Function Call let res = cntZeroRange(R) - cntZeroRange(L - 1); Â
// Print answer document.write(res + "<br>" ); Â
Â
// This code is contributed by avanitrachhadiya2155 Â
</script> |
7
Â
Time Complexity: O(log10(R) * log10(L) sqrt(log10(R))* 10 * 4))
Auxiliary Space: O(log10(R) * log10(L) * 4)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 zambiatek!