Count numbers in a given range having prime and non-prime digits at prime and non-prime positions respectively

• Difficulty Level : Medium
• Last Updated : 18 Jun, 2021

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

 

Output:

7

Time Complexity: O(log10(R) * log10(L) sqrt(log10(R))* 10 * 4))
Auxiliary Space: O(log10(R) * log10(L) * 4)

My Personal Notes arrow_drop_up
Recommended Articles
Page :