Open In App

Count Numbers in Range with difference between Sum of digits at even and odd positions as Prime

Last Updated : 22 Nov, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

Given a range [l, r]. The task is to count the numbers in the range having difference between the sum of digits at even position and sum of digits at odd position is a Prime Number. Consider the position of least significant digit in the number as an odd position.

Examples: 

Input : l = 1, r = 50
Output : 6
Explanation : Only, 20, 30, 31, 41, 42 and 50 are valid numbers.

Input : l = 50, r = 100
Output : 18

Main Idea

The key observation is that the maximum difference between the sum of digits at even positions and odd positions in a number with up to 19 digits is 9×10-0×9=90. This occurs when all 10 odd-position digits are 9 and all even-position digits are 0. Since this difference cannot exceed 90, we only need to check whether the difference falls within the range of the first few prime numbers. Checking the first 100 prime numbers (which go beyond 90) is sufficient to cover all possible cases, as no difference will exceed 90 regardless of the arrangement of the digits. This significantly reduces the computation needed.

Using Brute Force Method - O(r*len(r)) Time and O(1) Space

The idea is to traverse all possible integers in the range [l, r] and for each number, check if the difference between the sum of digits at even position and sum of digits at odd position is a Prime Number.

C++
// C++ program to count Numbers in Range
// with difference between Sum of digits
// at even and odd positions as Prime
#include <bits/stdc++.h>
using namespace std;

int count(int l, int r) {

    // Set to store the first
    // 100 prime numbers.
    unordered_set<int> primes = 
    { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
            31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
            73, 79, 83, 89, 97};

    int ans = 0;

    // Check for all numbers
    // in range [l, r].
    for (int i = l; i <= r; i++) {
        int num = i;
        int oddSum = 0, evenSum = 0;

        while (num > 0) {
            oddSum += num % 10;
            num = num / 10;
            if (num > 0) {
                evenSum += num % 10;
                num = num / 10;
            }
        }

        int diff = evenSum - oddSum;

        // If difference is prime,
        // increment the answer.
        if (primes.find(diff) != primes.end()) {
            ans++;
        }
    }

    return ans;
}

int main() {
  
    int l = 1, r = 50;
    cout << count(l, r) << endl;
    return 0;
}
Java
// Java program to count Numbers in Range 
// with difference between Sum of digits
// at even and odd positions as Prime

import java.util.HashSet;
import java.util.Arrays;

class GfG {

    static int count(int l, int r) {

        // Set to store the first
        // 100 prime numbers.
        HashSet<Integer> primes = new HashSet<>(Arrays.asList(
            2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
            31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
            73, 79, 83, 89, 97
        ));


        int ans = 0;

        // Check for all numbers 
        // in range [l, r].
        for (int i = l; i <= r; i++) {
            int num = i;
            int oddSum = 0, evenSum = 0;

            while (num > 0) {
                oddSum += num % 10;
                num = num / 10;
                if (num > 0) {
                    evenSum += num % 10;
                    num = num / 10;
                }
            }

            int diff = evenSum - oddSum;

            // If difference is prime,
            // increment the answer.
            if (primes.contains(diff)) {
                ans++;
            }
        }

        return ans;
    }

    public static void main(String[] args) {
        int l = 1, r = 50;
        System.out.println(count(l, r));
    }
}
Python
# Python program to count Numbers in Range 
# with difference between Sum of digits
# at even and odd positions as Prime

def count(l, r):
  
    # Set to store the first
    # 100 prime numbers.
    primes = {
        2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
        31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
        73, 79, 83, 89, 97
    }
    
    ans = 0

    # Check for all numbers 
    # in range [l, r].
    for i in range(l, r + 1):
        num = i
        oddSum = 0
        evenSum = 0

        while num > 0:
            oddSum += num % 10
            num //= 10
            if num > 0:
                evenSum += num % 10
                num //= 10

        diff = evenSum - oddSum

        # If difference is prime,
        # increment the answer.
        if diff in primes:
            ans += 1

    return ans

if __name__ == "__main__":
    l, r = 1, 50
    print(count(l, r))
C#
// C# program to count Numbers in Range 
// with difference between Sum of digits
// at even and odd positions as Prime

using System;
using System.Collections.Generic;

class GfG {

    static int count(int l, int r) {

        // Set to store the first
        // 100 prime numbers.
        HashSet<int> primes = new HashSet<int>() {
            2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
            31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
            73, 79, 83, 89, 97
        };

        int ans = 0;

        // Check for all numbers 
        // in range [l, r].
        for (int i = l; i <= r; i++) {
            int num = i;
            int oddSum = 0, evenSum = 0;

            while (num > 0) {
                oddSum += num % 10;
                num /= 10;
                if (num > 0) {
                    evenSum += num % 10;
                    num /= 10;
                }
            }

            int diff = evenSum - oddSum;

            // If difference is prime,
            // increment the answer.
            if (primes.Contains(diff)) {
                ans++;
            }
        }

        return ans;
    }

    static void Main(string[] args) {
        int l = 1, r = 50;
        Console.WriteLine(count(l, r));
    }
}
JavaScript
// JavaScript program to count Numbers in Range 
// with difference between Sum of digits
// at even and odd positions as Prime

function count(l, r) {
    
    // Set to store the first
    // 100 prime numbers.
    const primes = new Set([
        2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
        31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
        73, 79, 83, 89, 97
    ]);

    let ans = 0;

    // Check for all numbers 
    // in range [l, r].
    for (let i = l; i <= r; i++) {
        let num = i;
        let oddSum = 0, evenSum = 0;

        while (num > 0) {
            oddSum += num % 10;
            num = Math.floor(num / 10);
            if (num > 0) {
                evenSum += num % 10;
                num = Math.floor(num / 10);
            }
        }

        const diff = evenSum - oddSum;

        // If difference is prime,
        // increment the answer.
        if (primes.has(diff)) {
            ans++;
        }
    }

    return ans;
}

const l = 1, r = 50;
console.log(count(l, r));

Output
6

Using Digit Dynamic Programming - O(len(r)) Time and O(len(r)) Space

The idea involves constructing numbers from the most significant digit (MSD) to the least significant digit (LSD) while maintaining a condition on the difference between the sum of digits at even and odd positions. We will use Digit DP to recursively explore all possible numbers that meet the criteria, while keeping track of:

  • The current difference between the sum of digits at even and odd positions.
  • Whether we are still bound by the upper limit.
  • The current position we are at in the number being formed.

DP States:

  • i is the current digit position we are processing.
  • diff is the difference between the sum of digits at even positions and the sum of digits at odd positions.
  • tight is a boolean flag indicating whether we are still constrained by the upper bound (i.e., if we are forming a number that must be less than or equal to a given number).

Base Case:

When we have processed all digits (i.e., when i == length of the number), we check whether the absolute value of diff is a prime number. If it is prime, we return 1 (count this number); otherwise, return 0.

Step by step explanation:

  • For each position i, loop through possible digits from 0 to the current digit (if tight is true) or from 0 to 9 (if tight is false).
  • Update the diff based on whether the position i is even or odd:
    • Add the digit to diff if the position is even.
    • Subtract the digit from diff if the position is odd.
  • Recursively call the function for the next digit position, considering the new value of diff and whether we are still tight.
  • Once all digits have been processed, check if the b of diff is prime.
  • To get the result for the range [l, r], first compute the count of valid numbers in the range [0, r] and then subtract the count of valid numbers in the range [0, l-1].
C++
// C++ program to count Numbers in Range
// with difference between Sum of digits
// at even and odd positions as Prime
#include <bits/stdc++.h>
using namespace std;

int countRecur(int i, int diff, int tight, string &num, unordered_set<int> &primes,
               vector<vector<vector<int>>> &memo) {
    if (i == num.length()) {
        if (primes.find(diff) != primes.end()) {
            return 1;
        }
        return 0;
    }

    if (memo[i][diff + 90][tight] != -1) {
        return memo[i][diff + 90][tight];
    }

    int ans = 0;
    int digit = num[i] - '0';

    // Check if tight constraint is still
    // present.
    int limit = (tight) ? digit : 9;

    for (int j = 0; j <= limit; j++) {

        // Set new diff on basis of odd
        // or even index.
        int newDiff = (num.length() - i) % 2 == 1 ? diff - j : diff + j;

        ans += countRecur(i + 1, newDiff, tight && (j == digit), num, primes, memo);
    }

    return memo[i][diff + 90][tight] = ans;
}

int count(int l, int r) {

    // Set to store the first
    // 100 prime numbers.
    unordered_set<int> primes = 
    {2,  3,  5,  7,  11, 13, 17, 19, 23, 29, 31, 37, 41,
 	43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97};

    // Memoization table (19 digits, 181
    // diff range, 2 tight conditions)
    vector<vector<vector<int>>> memo(19,
	vector<vector<int>>(181, vector<int>(2, -1)));

    // Get count of [0, r]
    string r1 = to_string(r);
    int rCnt = countRecur(0, 0, 1, r1, primes, memo);

    // Reset dp
    for (int i = 0; i < 19; i++) {
        for (int j = 0; j < 181; j++) {
            for (int k = 0; k < 2; k++) {
                memo[i][j][k] = -1;
            }
        }
    }

    // Get count of [0, l-1]
    string l1 = to_string(l - 1);
    int lCnt = countRecur(0, 0, 1, l1, primes, memo);

    return rCnt - lCnt;
}

int main() {
  
    int l = 1, r = 50;
    cout << count(l, r) << endl;

    return 0;
}
Java
// Java program to count Numbers in Range 
// with difference between Sum of digits
// at even and odd positions as Prime

import java.util.*;

class GfG {

    static int countRecur(int i, int diff, int tight, String num,
                          HashSet<Integer> primes, int[][][] memo) {
        if (i == num.length()) {
            if (primes.contains(diff)) {
                return 1;
            }
            return 0;
        }

        if (memo[i][diff + 90][tight] != -1) {
            return memo[i][diff + 90][tight];
        }

        int ans = 0;
        int digit = num.charAt(i) - '0';

        // Check if tight constraint is still
        // present.
        int limit = (tight==1) ? digit : 9;

        for (int j = 0; j <= limit; j++) {

            // Set new diff on basis of odd 
            // or even index.
            int newDiff = 
            (num.length() - i) % 2 == 1 ? diff - j : diff + j;

            ans += countRecur(i + 1, newDiff,
            tight==1 && (j == digit)?1:0, num, primes, memo);
        }

        return memo[i][diff + 90][tight] = ans;
    }

    static int count(int l, int r) {

        // Set to store the first
        // 100 prime numbers.
        HashSet<Integer> primes = new HashSet<>(Arrays.asList(
            2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
            31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
            73, 79, 83, 89, 97
        ));

        // Memoization table (19 digits, 181
        // diff range, 2 tight conditions)
        int[][][] memo = new int[19][181][2];
        for (int i = 0; i < 19; i++) {
            for (int j = 0; j < 181; j++) {
                for (int k = 0; k < 2; k++) {
                    memo[i][j][k] = -1;
                }
            }
        }

        // Get count of [0, r]
        String r1 = Integer.toString(r);
        int rCnt = countRecur(0, 0, 1, r1, primes, memo);

        // Reset dp
        for (int i = 0; i < 19; i++) {
            for (int j = 0; j < 181; j++) {
                for (int k = 0; k < 2; k++) {
                    memo[i][j][k] = -1;
                }
            }
        }

        // Get count of [0, l-1]
        String l1 = Integer.toString(l - 1);
        int lCnt = countRecur(0, 0, 1, l1, primes, memo);

        return rCnt - lCnt;
    }

    public static void main(String[] args) {
        int l = 1, r = 50;
        System.out.println(count(l, r));
    }
}
Python
# Python program to count Numbers in Range 
# with difference between Sum of digits
# at even and odd positions as Prime

def countRecur(i, diff, tight, num, primes, memo):
    if i == len(num):
        if diff in primes:
            return 1
        return 0

    if memo[i][diff + 90][tight] != -1:
        return memo[i][diff + 90][tight]

    ans = 0
    digit = int(num[i])

    # Check if tight constraint is still
    # present.
    limit = digit if tight else 9

    for j in range(limit + 1):

        # Set new diff on basis of odd 
        # or even index.
        newDiff = diff - j if (len(num) - i) % 2 == 1 else diff + j

        ans += countRecur(i + 1, newDiff, tight and (j == digit), num, primes, memo)

    memo[i][diff + 90][tight] = ans
    return ans

def count(l, r):

    # Set to store the first
    # 100 prime numbers.
    primes = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
              31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
              73, 79, 83, 89, 97}

    # Memoization table (19 digits, 181 
    # diff range, 2 tight conditions)
    memo = [[[-1 for _ in range(2)] for _ in range(181)] for _ in range(19)]

    # Get count of [0, r]
    r1 = str(r)
    rCnt = countRecur(0, 0, 1, r1, primes, memo)

    # Reset dp
    memo = [[[-1 for _ in range(2)] for _ in range(181)] for _ in range(19)]

    # Get count of [0, l-1]
    l1 = str(l - 1)
    lCnt = countRecur(0, 0, 1, l1, primes, memo)

    return rCnt - lCnt

if __name__ == "__main__":
    l, r = 1, 50
    print(count(l, r))
C#
// C# program to count Numbers in Range 
// with difference between Sum of digits
// at even and odd positions as Prime

using System;
using System.Collections.Generic;

class GfG {

    static int countRecur(int i, int diff, int tight, string num,
                          HashSet<int> primes, int[,,] memo) {
        if (i == num.Length) {
            if (primes.Contains(diff)) {
                return 1;
            }
            return 0;
        }

        if (memo[i, diff + 90, tight] != -1) {
            return memo[i, diff + 90, tight];
        }

        int ans = 0;
        int digit = num[i] - '0';

        // Check if tight constraint is still
        // present.
        int limit = tight == 1 ? digit : 9;

        for (int j = 0; j <= limit; j++) {

            // Set new diff on basis of odd 
            // or even index.
            int newDiff = (num.Length - i) % 2 == 1 ? diff - j : diff + j;

            ans += countRecur(i + 1, newDiff,
                    tight == 1 && (j == digit)?1:0, num, primes, memo);
        }

        memo[i, diff + 90, tight] = ans;
        return ans;
    }

    static int count(int l, int r) {

        // Set to store the first
        // 100 prime numbers.
        HashSet<int> primes = new HashSet<int>() {
            2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
            31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
            73, 79, 83, 89, 97
        };

        // Memoization table (19 digits, 181
        // diff range, 2 tight conditions)
        int[,,] memo = new int[19, 181, 2];
        for (int i = 0; i < 19; i++) {
            for (int j = 0; j < 181; j++) {
                for (int k = 0; k < 2; k++) {
                    memo[i, j, k] = -1;
                }
            }
        }

        // Get count of [0, r]
        string r1 = r.ToString();
        int rCnt = countRecur(0, 0, 1, r1, primes, memo);

        // Reset dp
        for (int i = 0; i < 19; i++) {
            for (int j = 0; j < 181; j++) {
                for (int k = 0; k < 2; k++) {
                    memo[i, j, k] = -1;
                }
            }
        }

        // Get count of [0, l-1]
        string l1 = (l - 1).ToString();
        int lCnt = countRecur(0, 0, 1, l1, primes, memo);

        return rCnt - lCnt;
    }

    static void Main(string[] args) {
        int l = 1, r = 50;
        Console.WriteLine(count(l, r));
    }
}
JavaScript
// JavaScript program to count Numbers in Range 
// with difference between Sum of digits
// at even and odd positions as Prime

function countRecur(i, diff, tight, num, primes, memo) {
    if (i === num.length) {
        if (primes.has(diff)) {
            return 1;
        }
        return 0;
    }

    if (memo[i][diff + 90][tight] !== -1) {
        return memo[i][diff + 90][tight];
    }

    let ans = 0;
    let digit = num[i] - '0';

    // Check if tight constraint is still
    // present.
    let limit = tight ? digit : 9;

    for (let j = 0; j <= limit; j++) {

        // Set new diff on basis of odd 
        // or even index.
        let newDiff = (num.length - i) % 2 === 1 ? diff - j : diff + j;

        ans += countRecur(i + 1, newDiff,
            tight && (j === digit)?1:0, num, primes, memo);
    }

    memo[i][diff + 90][tight] = ans;
    return ans;
}

function count(l, r) {

    // Set to store the first
    // 100 prime numbers.
    let primes = new Set([2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
        31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
        73, 79, 83, 89, 97]);

    // Memoization table (19 digits, 181
    // diff range, 2 tight conditions)
    let memo = Array.from({ length: 19 }, () =>
        Array.from({ length: 181 }, () =>
            Array(2).fill(-1)
        )
    );

    // Get count of [0, r]
    let r1 = r.toString();
    let rCnt = countRecur(0, 0, 1, r1, primes, memo);

    // Reset dp
    memo = Array.from({ length: 19 }, () =>
        Array.from({ length: 181 }, () =>
            Array(2).fill(-1)
        )
    );

    // Get count of [0, l-1]
    let l1 = (l - 1).toString();
    let lCnt = countRecur(0, 0, 1, l1, primes, memo);

    return rCnt - lCnt;
}

let l = 1, r = 50;
console.log(count(l, r));

Output
6

Next Article

Similar Reads