Skip to content
Related Articles

Related Articles

    Improve Article
    Save Article
    Like Article

    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: 

    cnt1XPrime(sum, len, tight)              [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 <bits/stdc++.h>
    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




    <script>
     
    // Javascript program to implement
    // the above approach
     
    // Function to find all prime
    // numbers in the range [1, 100000]
    // using Sieve of Eratosthenes
    // technique
    function sieve()
    {
         
        // isPrime[i] stores if i
        // is a prime number or not
        let isPrime = new Array(100001);
     
        for(let 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(let i = 2; i * i < 100001; i++)
        {
             
            // If i is a prime number
            if (isPrime[i] == true)
            {
                for(let 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
    function cnt1XPrime(sum, len, tight, X,
                        isPrime, 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
        let end = (tight == 1) ?
         (X[len].charCodeAt(0) - 48) : 9;
     
        // Stores count of numbers by
        // placing all possible values
        // at current index
        let res = 0;
     
        // Place all possible values at
        // current position
        for(let 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]
    function cntLRprime(L, R)
    {
         
        // Stores the value of (L - 1)
        // in the form of string
        let LStr = (L - 1).toString();
     
        // Stores the value of (R)
        // in the form of string
        let RStr = (R).toString();
     
        // Stores values of overlapping
        // subproblems
        let dp = new Array(1000);
     
        // Initialize dp[][][] array
        for(let i = 0; i < 1000; i++)
        {
            dp[i] = new Array(100);
            for(let j = 0; j < 100; j++)
            {
                dp[i][j] = new Array(2);
                for(let k = 0; k < 2; k++)
                    dp[i][j][k] = -1;
            }
        }
         
        // isPrime[i] stores if i
        // is a prime number or not
        let isPrime = sieve();
     
        // Stores count of numbers in
        // range [1, LStr] with the
        // given conditions
        let cntL = cnt1XPrime(0, 0, 1, LStr,
                              isPrime, dp);
     
        // Initialize dp[][][] array.
        for(let i = 0; i < 1000; i++)
        {
            for(let j = 0; j < 100; j++)
            {
                for(let k = 0; k < 2; k++)
                    dp[i][j][k] = -1;
            }
        }
     
        // Stores count of numbers in range
        // [1, RStr] with the given conditions
        let 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
    let L = 11, R = 999;
     
    document.write(cntLRprime(L, R));
     
    // This code is contributed by avanitrachhadiya2155
     
    </script>

    
    

    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
    Recommended Articles
    Page :

    Start Your Coding Journey Now!