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++ 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 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 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# 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. |
<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> |
Output:
7
Time Complexity: O(log10(R) * log10(L) sqrt(log10(R))* 10 * 4))
Auxiliary Space: O(log10(R) * log10(L) * 4)