Skip to content
Related Articles

Related Articles

Improve Article

Count of numbers in range which are divisible by M and have digit D at odd places

  • Difficulty Level : Expert
  • Last Updated : 06 Jul, 2021

Given two numbers M, D, and an array arr[] which represents the range [L, R], the task is to count the numbers in the range [L, R] which is divisible by M, and the digit D occurs at every odd position. 

Note: The numbers might be large. So, the range array {L, R} is given in the form of a string.

Examples:  

Input: arr[] = {20, 32}, M = 2, D = 2 
Output:
Explanation: 
There are 4 numbers in the range [20, 32] which are divisible by 2 and 2 at the odd (first) position. They are: 
20, 24, 26, 28.

Input: arr[] = {40, 60}, M = 2, D = 5 
Output:
Explanation: 
There are 5 numbers in the range [40, 60] which are divisible by 2 and 5 at the odd (first) position. They are: 
50, 52, 54, 56, 58. 



Naive Approach: The naive approach for this problem is to take every number between L to R and check whether the digit D occurs at odd positions or not and whether the number is divisible by M or not. The time complexity of this solution will be O(N*K) where N is the count of numbers in the range [L, R] and K is the maximum number of digits in any number in the range [L, R].

Efficient Approach: The idea is to use the concept of digit-dp and find the number of combinations of the numbers that solve the problem. In order to find the count of numbers satisfying the condition, we find the count of numbers satisfying the condition up to the highest number R in the range. This includes all the 1 digit, 2 digit, 3 digit numbers. After finding this count, we simply subtract the count of numbers satisfying up to L – 1 from the above value to get the final answer.

  1. On assuming the numbers as a sequence of digits, we try to form an N digit number that follows the conditions at every iteration where N is the number of digits in the given upper range R. Let the count be C.
  2. This count C includes the 1-digit numbers, 2-digit numbers, 3-digit numbers … up to N-digit numbers where N is the number of digits in R.
  3. Similarly, we find the count of numbers satisfying the condition up to L – 1. Let this count be D.
  4. The required answer needed is the difference between both the counts C – D.
  5. The count of numbers satisfying the given condition is found out by the concept of digit dp.
  6. A three-dimensional table is formed and filled using this concept.

Below is the implementation of the above approach: 

C++14




// C++ program to find the count of numbers
// in the range [L, R] which are divisible
// by M and have digit D at the odd places
 
#include <bits/stdc++.h>
using namespace std;
#define ll long long int
 
// Variables to store M, N, D
ll m, n, d;
 
// Vector to store the digit number
// in the form of digits
vector<int> v;
ll const k = 1e9 + 7;
 
// Dp table to compute the answer
ll dp[2001][2001][2];
 
// Function to add the individual
// digits into the vector
void init(string s)
{
    memset(dp, -1, sizeof(dp));
    v.clear();
 
    // Iterating through the number
    // and adding the digits into
    // the vector
    for (int i = 0; i < s.size(); i++) {
        v.push_back(s[i] - '0');
    }
    n = s.size();
}
 
// Function to subtract 1 from a number
// represented in a form of a string
string number_minus_one(string a)
{
    string s = a.substr(1);
    string s1 = "";
 
    // Iterating through the number
    for (int i = 0; i < s.size() - 1; i++)
        s1 += '0';
 
    // If the first digit is 1, then make it 0
    // and add 9 at the end of the string.
    if (a[0] == 1 and s == s1) {
        ll l = s.size();
        a = "";
        a += '0';
        for (int i = 0; i < l; i++)
            a += '9';
    }
    else {
        for (int i = a.size() - 1; i >= 0; i--) {
 
            // If we need to subtract 1 from 0,
            // then make it 9 and subtract 1
            // from the previous digits
            if (a[i] == '0')
                a[i] = '9';
 
            // Else, simply subtract 1
            else {
                a[i] = (((a[i] - '0') - 1) + '0');
                break;
            }
        }
    }
    return a;
}
 
// Function to find the count of numbers
// in the range [L, R] which are divisible
// by M and have digit D at the odd places
ll fun(ll pos, ll sum, ll f)
{
 
    // Base case
    if (pos == n) {
        if (sum == 0) {
 
            // If we have built N-digit number
            // and the number is divisible
            // by m then we have got
            // one possible answer.
            return 1;
        }
        return 0;
    }
 
    // If the answer has already been computed,
    // then return the answer
    if (dp[pos][sum][f] != -1)
        return dp[pos][sum][f];
    ll lmt = 9;
 
    // The possible digits which we can
    // place at the pos position.
    if (!f)
        lmt = v[pos];
 
    ll ans = 0;
 
    // Iterating through all the digits
    for (ll i = 0; i <= lmt; i++) {
        if (i == d and pos % 2 == 1)
            ans += 0;
        else if (i != d and pos % 2 == 0)
            ans += 0;
        else {
            ll new_f = f;
 
            // If we have placed all the digits
            // up to pos-1 equal to their
            // limit and currently we are placing
            // a digit which is smaller than this
            // position's limit then we can place
            // 0 to 9 at all the next positions
            // to make the number smaller than R
            if (f == 0 and i < lmt)
                new_f = 1;
 
            // Calculating the number upto pos mod m.
            ll new_sum = sum;
 
            // Combinations of numbers as there are
            // 10 digits in the range [0, 9]
            new_sum *= 10;
            new_sum += i;
            new_sum %= m;
 
            // Recursively call the function
            // for the next position
            ans += fun(pos + 1, new_sum, new_f);
            ans %= k;
        }
    }
 
    // Returning the final answer
    return dp[pos][sum][f] = ans;
}
 
// Function to call the function
// for every query
void operations(string L, string R)
{
    init(R);
    ll ans = fun(0, 0, 0);
    L = number_minus_one(L);
    init(L);
    ans -= fun(0, 0, 0);
    if (ans < 0)
        ans += k;
    cout << ans << "\n";
}
 
// Driver code
int main()
{
    m = 2, d = 2;
    ll Q = 1;
    string arr[][2] = { { "20", "32" } };
 
    for (ll i = 0; i < Q; i++) {
        operations(arr[i][0], arr[i][1]);
    }
 
    return 0;
}

Java




// Java program to find the count of numbers
// in the range [L, R] which are divisible
// by M and have digit D at the odd places
import java.util.ArrayList;
import java.util.Arrays;
 
class Graph{
 
// Variables to store M, N, D
static int m, n, d;
 
// Vector to store the digit number
// in the form of digits
static ArrayList<Integer> v = new ArrayList<>();
static final int k = (int) 1e9 + 7;
 
// Dp table to compute the answer
static int[][][] dp = new int[2001][2001][2];
 
// Function to add the individual
// digits into the vector
static void init(StringBuilder l)
{
    for(int i = 0; i < 2001; i++)
    {
        for(int j = 0; j < 2001; j++)
        {
            for(int k = 0; k < 2; k++)
            {
                dp[i][j][k] = -1;
            }
        }
    }
    v.clear();
     
    // Iterating through the number
    // and adding the digits into
    // the vector
    for(int i = 0; i < l.length(); i++)
    {
        v.add(l.charAt(i) - '0');
    }
    n = l.length();
  
}
 
// Function to subtract 1 from a number
// represented in a form of a String
static String number_minus_one(StringBuilder a)
{
    String s = a.substring(1);
  
    String s1 = "";
     
    // Iterating through the number
    for(int i = 0; i < s.length() - 1; i++)
        s1 += '0';
         
    // If the first digit is 1, then make it 0
    // and add 9 at the end of the String.
    if (a.charAt(0) == '1' && s.compareTo(s1) == 0)
    {
        int l = s.length();
        a = new StringBuilder("");
        a.append('0');
         
        for(int i = 0; i < l; i++)
            a.append('9');
       
    }
    else
    {
        for(int i = a.length() - 1; i >= 0; i--)
        {
             
            // If we need to subtract 1 from 0,
            // then make it 9 and subtract 1
            // from the previous digits
            if (a.charAt(i) == '0')
                a.setCharAt(i, '9');
                 
            // Else, simply subtract 1
            else
            {
                a.setCharAt(i, (char)(
                    ((a.charAt(i) - '0') - 1) + '0'));
                break;
            }
         
        }
    }
 
    return a.toString();
}
 
// Function to find the count of numbers
// in the range [L, R] which are divisible
// by M and have digit D at the odd places
static int fun(int pos, int sum, int f)
{
     
    // Base case
    if (pos == n)
    {
        if (sum == 0)
        {
             
            // If we have built N-digit number
            // and the number is divisible
            // by m then we have got
            // one possible answer.
            return 1;
        }
        return 0;
    }
 
    // If the answer has already been computed,
    // then return the answer
    if (dp[pos][sum][f] != -1)
        return dp[pos][sum][f];
         
    int lmt = 9;
 
    // The possible digits which we can
    // place at the pos position.
    if (f == 0)
        lmt = v.get(pos);
 
    int ans = 0;
 
    // Iterating through all the digits
    for(int i = 0; i <= lmt; i++)
    {
        if (i == d && pos % 2 == 1)
            ans += 0;
        else if (i != d && pos % 2 == 0)
            ans += 0;
        else
        {
            int new_f = f;
             
            // If we have placed all the digits
            // up to pos-1 equal to their
            // limit and currently we are placing
            // a digit which is smaller than this
            // position's limit then we can place
            // 0 to 9 at all the next positions
            // to make the number smaller than R
            if (f == 0 && i < lmt)
                new_f = 1;
 
            // Calculating the number upto pos mod m.
            int new_sum = sum;
 
            // Combinations of numbers as there are
            // 10 digits in the range [0, 9]
            new_sum *= 10;
            new_sum += i;
            new_sum %= m;
 
            // Recursively call the function
            // for the next position
            ans += fun(pos + 1, new_sum, new_f);
            ans %= k;
        }
    }
 
    // Returning the final answer
    return dp[pos][sum][f] = ans;
}
 
// Function to call the function
// for every query
static void operations(StringBuilder L,
                       StringBuilder R)
{
    init(R);
    int ans = fun(0, 0, 0);
    L = new StringBuilder(number_minus_one(L));
    init(L);
    ans -= fun(0, 0, 0);
     
    if (ans < 0)
        ans += k;
         
    System.out.println(ans);
}
 
// Driver code
public static void main(String[] args)
{
    m = 2;
    d = 2;
    int Q = 1;
     
    StringBuilder[][] arr = {
        { new StringBuilder("20"),
          new StringBuilder("32") } };
     
    for(int i = 0; i < Q; i++)
    {
        operations(arr[i][0], arr[i][1]);
    }
}
}
 
// This code is contributed by sanjeev2552

C#




// C# program to find the count of numbers
// in the range [L, R] which are divisible
// by M and have digit D at the odd places
using System;
using System.Collections.Generic;
class Graph{
 
// Variables to store M, N, D
static int m, n, d;
 
// Vector to store the digit number
// in the form of digits
static List<int> v = new List<int>();
static int k = (int) 1e9 + 7;
 
// Dp table to compute the answer
static int[,,] dp = new int[2001, 2001, 2];
 
// Function to add the individual
// digits into the vector
static void init(string l)
{
    for(int i = 0; i < 2001; i++)
    {
        for(int j = 0; j < 2001; j++)
        {
            for(int k = 0; k < 2; k++)
            {
                dp[i, j, k] = -1;
            }
        }
    }
    v.Clear();
     
    // Iterating through the number
    // and adding the digits into
    // the vector
    for(int i = 0; i < l.Length; i++)
    {
        v.Add(l[i] - '0');
    }
    n = l.Length;
   
}
 
// Function to subtract 1 from a number
// represented in a form of a String
static string number_minus_one(string a)
{
    string s = a.Substring(1);
    string s1 = "";
     
    // Iterating through the number
    for(int i = 0; i < s.Length - 1; i++)
        s1 += '0';
 
    // If the first digit is 1, then make it 0
    // and add 9 at the end of the String.
    if (a[0] == '1' && String.Compare(s, s1) == 0)
    {
        int l = s.Length;     
        a = a.Replace(a[0], '0');       
        for(int i = 0; i < l; i++)
            a+='9';
    }
    else
    {
        for(int i = a.Length - 1; i >= 0; i--)
        {
             
            // If we need to subtract 1 from 0,
            // then make it 9 and subtract 1
            // from the previous digits
            if (a[i] == '0')
                a = a.Replace(a[i], '9');
                 
            // Else, simply subtract 1
            else
            {
                a = a.Replace(a[i], (char)(((a[i] - '0') - 1) + '0'));
                break;
            }     
        }
    }
    return a.ToString();
}
 
// Function to find the count of numbers
// in the range [L, R] which are divisible
// by M and have digit D at the odd places
static int fun(int pos, int sum, int f)
{
     
    // Base case
    if (pos == n)
    {
        if (sum == 0)
        {
             
            // If we have built N-digit number
            // and the number is divisible
            // by m then we have got
            // one possible answer.
            return 1;
        }
        return 0;
    }
 
    // If the answer has already been computed,
    // then return the answer
    if (dp[pos, sum, f] != -1)
        return dp[pos, sum, f];      
    int lmt = 9;
 
    // The possible digits which we can
    // place at the pos position.
    if (f == 0)
        lmt = v[pos];
    int ans = 0;
 
    // Iterating through all the digits
    for(int i = 0; i <= lmt; i++)
    {
        if (i == d && pos % 2 == 1)
            ans += 0;
        else if (i != d && pos % 2 == 0)
            ans += 0;
        else
        {
            int new_f = f;
             
            // If we have placed all the digits
            // up to pos-1 equal to their
            // limit and currently we are placing
            // a digit which is smaller than this
            // position's limit then we can place
            // 0 to 9 at all the next positions
            // to make the number smaller than R
            if (f == 0 && i < lmt)
                new_f = 1;
 
            // Calculating the number upto pos mod m.
            int new_sum = sum;
 
            // Combinations of numbers as there are
            // 10 digits in the range [0, 9]
            new_sum *= 10;
            new_sum += i;
            new_sum %= m;
 
            // Recursively call the function
            // for the next position
            ans += fun(pos + 1, new_sum, new_f);
            ans %= k;
        }
    }
 
    // Returning the final answer
    dp[pos, sum, f] = ans;
  return dp[pos, sum, f];
}
 
// Function to call the function
// for every query
static void operations(string L, string R)
{
    init(R);
    int ans = fun(0, 0, 0);
    L = number_minus_one(L);
    init(L);
    ans -= fun(0, 0, 0);
     
    if (ans < 0)
        ans += k;
         
    Console.WriteLine(ans);
}
 
// Driver code
public static void Main(String[] args)
{
    m = 2;
    d = 2;
    int Q = 1;   
    string[,] arr = { {"20",
          "32"  }}; 
    for(int i = 0; i < Q; i++)
    {
        operations(arr[i, 0], arr[i, 1]);
    }
}
}
 
// This code is contributed by chitranayal

Javascript




<script>
// Javascript program to find the count of numbers
// in the range [L, R] which are divisible
// by M and have digit D at the odd places
 
 
// Variables to store M, N, D
var m, n, d;
 
// Vector to store the digit number
// in the form of digits
var v = [];
var k = 1000000007;
 
// Dp table to compute the answer
var dp =  Array(2001);
 
for(var i = 0; i<2001;i++)
{
    dp[i] = Array.from(Array(2001), ()=>Array(2));
}
 
// Function to add the individual
// digits into the vector
function init(l)
{
    for(var i = 0; i < 2001; i++)
    {
        for(var j = 0; j < 2001; j++)
        {
            for(var k = 0; k < 2; k++)
            {
                dp[i][j][k] = -1;
            }
        }
    }
    v = [];
     
    // Iterating through the number
    // and adding the digits into
    // the vector
    for(var i = 0; i < l.length; i++)
    {
        v.push(l[i].charCodeAt(0) - '0'.charCodeAt(0));
    }
    n = l.length;
   
}
 
// Function to subtract 1 from a number
// represented in a form of a String
function number_minus_one(a)
{
    var s = a.substring(1);
    var s1 = "";
     
    // Iterating through the number
    for(var i = 0; i < s.length - 1; i++)
        s1 += '0';
 
    // If the first digit is 1, then make it 0
    // and add 9 at the end of the String.
    if (a[0] == '1' && s === s1)
    {
        var l = s.length;     
        a = a.replace(a[0], '0');       
        for(var i = 0; i < l; i++)
            a+='9';
    }
    else
    {
        for(var i = a.length - 1; i >= 0; i--)
        {
             
            // If we need to subtract 1 from 0,
            // then make it 9 and subtract 1
            // from the previous digits
            if (a[i] == '0')
                a = a.replace(a[i], '9');
                 
            // Else, simply subtract 1
            else
            {
                a = a.replace(a[i], String.fromCharCode(((a[i].charCodeAt(0) - '0'.charCodeAt(0)) - 1) + '0'.charCodeAt(0)));
                break;
            }     
        }
    }
    return a.toString();
}
 
// Function to find the count of numbers
// in the range [L, R] which are divisible
// by M and have digit D at the odd places
function fun(pos, sum, f)
{
     
    // Base case
    if (pos == n)
    {
        if (sum == 0)
        {
             
            // If we have built N-digit number
            // and the number is divisible
            // by m then we have got
            // one possible answer.
            return 1;
        }
        return 0;
    }
 
    // If the answer has already been computed,
    // then return the answer
    if (dp[pos][sum][f] != -1)
        return dp[pos][sum][f];      
    var lmt = 9;
 
    // The possible digits which we can
    // place at the pos position.
    if (f == 0)
        lmt = v[pos];
    var ans = 0;
 
    // Iterating through all the digits
    for(var i = 0; i <= lmt; i++)
    {
        if (i == d && pos % 2 == 1)
            ans += 0;
        else if (i != d && pos % 2 == 0)
            ans += 0;
        else
        {
            var new_f = f;
             
            // If we have placed all the digits
            // up to pos-1 equal to their
            // limit and currently we are placing
            // a digit which is smaller than this
            // position's limit then we can place
            // 0 to 9 at all the next positions
            // to make the number smaller than R
            if (f == 0 && i < lmt)
                new_f = 1;
 
            // Calculating the number upto pos mod m.
            var new_sum = sum;
 
            // Combinations of numbers as there are
            // 10 digits in the range [0, 9]
            new_sum *= 10;
            new_sum += i;
            new_sum %= m;
 
            // Recursively call the function
            // for the next position
            ans += fun(pos + 1, new_sum, new_f);
            ans %= k;
        }
    }
 
    // Returning the final answer
    dp[pos][sum][f] = ans;
  return dp[pos][sum][f];
}
 
// Function to call the function
// for every query
function operations(L, R)
{
    init(R);
    var ans = fun(0, 0, 0);
    L = number_minus_one(L);
    init(L);
    ans -= fun(0, 0, 0);
     
    if (ans < 0)
        ans += k;
         
    document.write(ans + "<br>");
}
 
// Driver code
m = 2;
d = 2;
var Q = 1;   
var arr = [["20", "32"]]; 
for(var i = 0; i < Q; i++)
{
    operations(arr[i][0], arr[i][1]);
}
 
</script>
Output: 
4

 

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.




My Personal Notes arrow_drop_up
Recommended Articles
Page :