Count numbers in range [L, R] whose sum of digits is a Prime Number

• Difficulty Level : Expert
• Last Updated : 15 Jun, 2021

Given two integers L and R, the task is to count all the numbers in the range [L, R] whose sum of digits is a prime number.

Examples:

Input: L = 1, R = 10
Output:
Explanation:
Numbers in the range L(= 1) to R(= 10), whose sum of digits is a prime number are {3, 5, 7}. Therefore, the required output is 3.

Input: L = 11, R = 999
Output: 336

Naive Approach: The simplest approach to solve this problem is to traverse all the numbers in the range [L, R] and for each number, check if the sum of digits of the number is a prime number or not. If found to be true, increment the count and finally, print the count as the required answer.

Time Complexity: O((R – L + 1) * sqrt(R))
Auxiliary Space: O(1)

Efficient Approach: The problem can be solved using Digit DP. The idea is to count the numbers in the range [1, R] whose sum of digits is a prime number and subtract the count of the numbers in the range [1, L â€“ 1] whose sum of digits is a prime number. Following are the recurrence relations:

[Tex]= \sum^{9}_{i=0} cnt1XPrime(sum + i, len + 1, tight \& (i==end))             [/Tex]

cnt1XPrime(sum, len, tight): Stores the count of numbers in the range [1, X] with the following constraints:
sum= Stores sum of digits of a number in the range [1, X]
len = count of digits in X
tight = Boolean value to check if the current digits range is restricted or not.

Follow the steps below to solve the problem:

• Initialize a 3D array dp[sum][len][tight] to compute and store the values of all subproblems of the above recurrence relation.
• Finally, return the value of dp[sum][len][tight].

Below is the implementation of the above approach:

C++

 // C++ program to implement // the above approach   #include  using namespace std;   // Function to find all prime numbers // in the range [1, 100000] using // Sieve of Eratosthenes technique vector<bool> sieve() {     // isPrime[i] stores if i     // is a prime number or not.     vector<bool> isPrime(100001,                          true);       // 0 is not a prime number     isPrime[0] = false;       // 1 is not prime number     isPrime[1] = false;       // Traverse the range to check if     // i is a prime number or not     for (int i = 2; i * i < 100001;          i++) {           // If i is a prime number         if (isPrime[i]) {             for (int j = i * i;                  j < 100001; j += i) {                   // Mark its multiples non-prime                 isPrime[j] = false;             }         }     }       return isPrime; }   // Function to count all numbers in // the range[1, X] whose sum of digits // is a prime number int cnt1XPrime(int sum, int len, bool tight,                string X, vector<bool>& isPrime,                int dp[1000][100][2]) {     // If count of digits in current number     // is equal to the count of digits in X     if (len == X.length()) {           // If sum is a prime number         return isPrime[sum];     }       // If already computed subproblem     // occurred     if (dp[sum][len][tight] != -1) {         return dp[sum][len][tight];     }           // Stores maximum possible value     // at current digit of the number     int end = tight ? (X[len] - '0') : 9;       // Stores count of numbers by placing     // all possible values at current index     int res = 0;       // Place all possible values at     // current position     for (int i = 0; i <= end; i++) {           // Update res         res += cnt1XPrime(sum + i, len + 1,                           (tight & (i == end)),                            X, isPrime, dp);     }        dp[sum][len][tight]=res;        return res; }   // Function to count the numbers in // the range[L, R] int cntLRprime(int L, int R) {     // Stores the value of (L - 1)     // in the form of string     string LStr = to_string(L - 1);       // Stores the value of (R)     // in the form of string     string RStr = to_string(R);       // Stores values of overlapping     // subproblems     int dp[1000][100][2];       // Initialize dp[][][] array     memset(dp, -1, sizeof(dp));       // isPrime[i] stores if i     // is a prime number or not     vector<bool> isPrime         = sieve();     // Stores count of numbers in range     // [1, LStr] with the given conditions     int cntL = cnt1XPrime(0, 0, 1, LStr,                           isPrime, dp);       // Initialize dp[][][] array.     memset(dp, -1, sizeof(dp));       // Stores count of numbers in range     // [1, RStr] with the given conditions     int cntR = cnt1XPrime(0, 0, 1, RStr,                           isPrime, dp);       // Return numbers in the range [L, R]     // whose sum of digits is a prime number     return (cntR - cntL); }   // Driver Code int main() {     int L = 11, R = 999;     cout << cntLRprime(L, R);       return 0; }

Java

 // Java program to implement // the above approach import java.util.*; class solution {       // Function to find all prime     // numbers in the range [1, 100000]     // using Sieve of Eratosthenes     // technique     static boolean[] sieve()     {         // isPrime[i] stores if i         // is a prime number or not         boolean[] isPrime = new boolean[100001];           for (int i = 0; i < 100001; i++)             isPrime[i] = true;           // 0 is not a prime number         isPrime[0] = false;           // 1 is not prime number         isPrime[1] = false;           // Traverse the range to check if         // i is a prime number or not         for (int i = 2; i * i < 100001; i++) {             // If i is a prime number             if (isPrime[i] == true) {                 for (int j = i * i; j < 100001; j += i) {                     // Mark its multiples                     // non-prime                     isPrime[j] = false;                 }             }         }           return isPrime;     }       // Function to count all numbers in     // the range[1, X] whose sum of digits     // is a prime number     static int cnt1XPrime(int sum, int len, int tight,                           String X, boolean[] isPrime,                           int[][][] dp)     {         // If count of digits in current         // number is equal to the count of         // digits in X         if (len == X.length()) {             // If sum is a prime number             return isPrime[sum] ? 1 : 0;         }           // If already computed subproblem         // occurred         if (dp[sum][len][tight] != -1) {             return dp[sum][len][tight];         }           // Stores maximum possible value         // at current digit of the number         int end = (tight == 1) ? (X.charAt(len) - 48) : 9;           // Stores count of numbers by         // placing all possible values         // at current index         int res = 0;           // Place all possible values at         // current position         for (int i = 0; i <= end; i++) {             // Update res             res += cnt1XPrime(                 sum + i, len + 1,                 (tight & ((i == end) ? 1 : 0)), X, isPrime,                 dp);         }           return dp[sum][len][tight] = res;     }       // Function to count the numbers in     // the range[L, R]     static int cntLRprime(int L, int R)     {         // Stores the value of (L - 1)         // in the form of string         String LStr = String.valueOf(L - 1);           // Stores the value of (R)         // in the form of string         String RStr = String.valueOf(R);           // Stores values of overlapping         // subproblems         int[][][] dp = new int[1000][100][2];           // Initialize dp[][][] array         for (int i = 0; i < 1000; i++) {             for (int j = 0; j < 100; j++) {                 for (int k = 0; k < 2; k++)                     dp[i][j][k] = -1;             }         }         // isPrime[i] stores if i         // is a prime number or not         boolean[] isPrime = sieve();           // Stores count of numbers in         // range [1, LStr] with the         // given conditions         int cntL = cnt1XPrime(0, 0, 1, LStr, isPrime, dp);           // Initialize dp[][][] array.         for (int i = 0; i < 1000; i++) {             for (int j = 0; j < 100; j++) {                 for (int k = 0; k < 2; k++)                     dp[i][j][k] = -1;             }         }           // Stores count of numbers in range         // [1, RStr] with the given conditions         int cntR = cnt1XPrime(0, 0, 1, RStr, isPrime, dp);           // Return numbers in the range         // [L, R] whose sum of digits         // is a prime number         return (cntR - cntL);     }       // Driver Code     public static void main(String args[])     {         int L = 11, R = 999;         System.out.print(cntLRprime(L, R));     } }   // This code is contributed by SURENDRA_GANGWAR

Python3

 # Python3 program to implement # the above approach isPrime = [True] * 100001   dp = [[[-1 for i in range(2)]        for i in range(100)]       for i in range(1000)]   # Function to find all prime numbers # in the range [1, 100000] using # Sieve of Eratosthenes technique     def sieve():       # 0 is not a prime number     isPrime[0] = False       # 1 is not prime number     isPrime[1] = False       # Traverse the range to check if     # i is a prime number or not     for i in range(2, 100001):         if i * i > 100001:             break           # If i is a prime number         if (isPrime[i]):             for j in range(i * i, 100001, i):                   # Mark its multiples non-prime                 isPrime[j] = False   # Function to count all numbers in # the range[1, X] whose sum of digits # is a prime number     def cnt1XPrime(sum, lenn, tight, X):       # If count of digits in current number     # is equal to the count of digits in X     if (lenn == len(X)):           # If sum is a prime number         return isPrime[sum]       # If already computed subproblem     # occurred     if (dp[sum][lenn][tight] != -1):         return dp[sum][lenn][tight]       # Stores maximum possible value     # at current digit of the number     end = 9       if tight:         end = ord(X[lenn]) - ord('0')       # Stores count of numbers by placing     # all possible values at current index     res = 0       # Place all possible values at     # current position     for i in range(end + 1):           # Update res         res += cnt1XPrime(sum + i,                           lenn + 1,                           (tight & (i == end)), X)       return dp[sum][lenn][tight] = res   # Function to count the numbers in # the range[L, R]     def cntLRprime(L, R):       # Stores the value of (L - 1)     # in the form of string     LStr = str(L - 1)       # Stores the value of (R)     # in the form of string     RStr = str(R)       # isPrime[i] stores if i     # is a prime number or not     sieve()       # Stores count of numbers in range     # [1, LStr] with the given conditions     cntL = cnt1XPrime(0, 0, 1, LStr)       # Initialize dp[][][] array.     for i in range(1000):         for j in range(100):             for z in range(2):                 dp[i][j][z] = -1       # Stores count of numbers in range     # [1, RStr] with the given conditions     cntR = cnt1XPrime(0, 0, 1, RStr)       # Return numbers in the range [L, R]     # whose sum of digits is a prime number     return (cntR - cntL)     # Driver code if __name__ == '__main__':       L = 11     R = 999       print(cntLRprime(L, R))   # This code is contributed by mohit kumar 29

C#

 // C# program to implement // the above approach using System; class GFG {       // Function to find all prime     // numbers in the range [1, 100000]     // using Sieve of Eratosthenes     // technique     static bool[] sieve()     {         // isPrime[i] stores if i         // is a prime number or not         bool[] isPrime = new bool[100001];           for (int i = 0; i < 100001; i++)             isPrime[i] = true;           // 0 is not a prime         // number         isPrime[0] = false;           // 1 is not prime         // number         isPrime[1] = false;           // Traverse the range to         // check if i is a prime         // number or not         for (int i = 2; i * i < 100001; i++) {             // If i is a prime number             if (isPrime[i] == true) {                 for (int j = i * i; j < 100001; j += i) {                     // Mark its multiples                     // non-prime                     isPrime[j] = false;                 }             }         }           return isPrime;     }       // Function to count all numbers     // in the range[1, X] whose sum     // of digits is a prime number     static int cnt1XPrime(int sum, int len, int tight,                           String X, bool[] isPrime,                           int[, , ] dp)     {         // If count of digits in current         // number is equal to the count of         // digits in X         if (len == X.Length) {             // If sum is a prime number             return isPrime[sum] ? 1 : 0;         }           // If already computed         // subproblem occurred         if (dp[sum, len, tight] != -1) {             return dp[sum, len, tight];         }           // Stores maximum possible value         // at current digit of the number         int end = (tight == 1) ? (X[len] - 48) : 9;           // Stores count of numbers by         // placing all possible values         // at current index         int res = 0;           // Place all possible values at         // current position         for (int i = 0; i <= end; i++) {             // Update res             res += cnt1XPrime(                 sum + i, len + 1,                 (tight & ((i == end) ? 1 : 0)), X, isPrime,                 dp);         }           return dp[sum, len, tight] = res;     }       // Function to count the numbers in     // the range[L, R]     static int cntLRprime(int L, int R)     {         // Stores the value of (L - 1)         // in the form of string           string LStr = (L - 1).ToString();           // Stores the value of (R)         // in the form of string         string RStr = (R).ToString();           // Stores values of overlapping         // subproblems         int[, , ] dp = new int[1000, 100, 2];           // Initialize dp[][][] array         for (int i = 0; i < 1000; i++) {             for (int j = 0; j < 100; j++) {                 for (int k = 0; k < 2; k++)                     dp[i, j, k] = -1;             }         }           // isPrime[i] stores if i         // is a prime number or not         bool[] isPrime = sieve();           // Stores count of numbers in         // range [1, LStr] with the         // given conditions         int cntL = cnt1XPrime(0, 0, 1, LStr, isPrime, dp);           // Initialize dp[][][] array.         for (int i = 0; i < 1000; i++) {             for (int j = 0; j < 100; j++) {                 for (int k = 0; k < 2; k++)                     dp[i, j, k] = -1;             }         }           // Stores count of numbers in         // range [1, RStr] with the         // given conditions         int cntR = cnt1XPrime(0, 0, 1, RStr, isPrime, dp);           // Return numbers in the range         // [L, R] whose sum of digits         // is a prime number         return (cntR - cntL);     }       // Driver Code     public static void Main(String[] args)     {         int L = 11, R = 999;         Console.Write(cntLRprime(L, R));     } }   // This code is contributed by Chitranayal

Javascript

 

Output

336

Time Complexity: O(sum * M * 10)
Auxiliary Space: O(sum * M), where sum denotes the maximum sum of digits of a number in the range [L, R] and M denotes the number of digits in R.

My Personal Notes arrow_drop_up
Related Articles