Skip to content
Related Articles

Related Articles

Improve Article

Count numbers from a given range whose adjacent digits are not co-prime

  • Last Updated : 02 Jun, 2021

Given an integer N, the task to print the count numbers from the range [1, N] whose adjacent digits are not co-prime. 

Two numbers A and B are said to be co-prime if the GCD of the two numbers is 1.

Examples:

Input: N = 30
Output: 15
Explanation: The numbers from [1, 30] which have non co-prime adjacent digits are {1, 2, 3, 4, 5, 6, 7, 8, 9, 20, 22, 24, 26, 28, 30}.

Input: N = 10000
Output: 1361



Naive Approach: The simplest approach to solve the problem is to iterate over the range 1 to N, and for each number from the range, check if GCD of their adjacent digits is equal to 1 or not and update the answer accordingly.
Time Complexity: O(NlogN) 
Auxiliary Space: O(1).

Efficient Approach: The above approach can also be optimized by using Dynamic Programming because it has overlapping subproblems and optimal substructure. The subproblems can be stored in dp[][][][] table using memoization where dp[i][bound][prev][allZeros] stores the answer from ‘i’th position to the end where bound is a boolean variable which ensures the number does not exceed N, prev stores the previous digit selected, allZeros is a boolean variable used to check if the all the digits selected till now are 0 or not

  1. Define a recursive function noncoprimeCount(i, bound, prev, allZeros) by performing the following steps.
    1. Convert the limit N to a string so that it will be iterated only over the length of the string and not the actual limit of N.
    2. Check the base case, which is if the entire string is traversed completely (i == N), then return 1 as a valid number in range [1, N] has been constructed.
    3. If the result of the state dp[i][bound][previous][allZeros] is already computed, return the value stored in dp[i][bound][previous][allZeros].
    4. At the current position ‘i’ any number from [0, 9] can be placed. While placing a digit, ensure the number does not exceed ‘R’ with the help of the variable bound. Also check if the GCD of the current digit and the previous digit(which is stored in prev) is greater than 1.There are two edge cases here:
      1. If the current index is 0, place any digit in the first position.
      2. If all the digits filled until now are zeros, i.e., allZeros is true, then it is valid to place 1 in the current position despite GCD(0, 1) = 1 as it is the most significant digit. Then set the allZeros to false.
    5. After placing a valid digit in the current position, recursively call the noncoprimeCount function for the element at index (i + 1).
    6. Return the sum of all possible valid placements of digits as the answer.
  • After completing the above steps, print the value of nocoprimeCount(0) as the result.

Below is the implementation of the above approach: 

C++




#include <bits/stdc++.h>
using namespace std;
  
int dp[100][2][10][2];
  
// Function to count numbers whose
// adjacent digits are not co-prime
int noncoprimeCount(int i, int N, string& S,
                    bool bound, int prev,
                    bool allZeros)
{
    // Base Case
    // If the entire string
    // is traversed
    if (i == N)
        return 1;
  
    int& val = dp[i][bound][prev][allZeros];
  
    // If the subproblem has
    // already been computed
    if (val != -1)
        return val;
  
    int cnt = 0;
  
    for (int j = 0; j <= (bound ? (S[i] - '0') : 9); ++j) {
  
        // A digit can be placed at
        // the current position if:
  
        // GCD of current and previous
        // digits is not equal to 1
        if ((__gcd(j, prev) != 1)
  
            // Current position is 0
            || (i == 0)
  
            // All encountered digits
            // until now are 0s
            || allZeros == 1) {
  
            cnt += noncoprimeCount(
                i + 1, N, S, bound
                                 & (j == (S[i] - '0')),
                j,
                allZeros & (j == 0));
        }
    }
  
    // Return the total
    // possible valid numbers
    return val = cnt;
}
  
// Function to count numbers whose
// adjacent digits are not co-prime
void noncoprimeCountUtil(int R)
{
    // Convert R to string.
    string S = to_string(R);
  
    // Length of string
    int N = S.length();
  
    // Initialize dp array with -1
    memset(dp, -1, sizeof dp);
  
    // Function call with initial values of
    // bound, allZeros, previous as 1, 1, 0
    int ans = noncoprimeCount(0, N, S, 1, 0, 1);
  
    // Subtract 1 from the answer, as 0 is included
    cout << ans - 1 << endl;
}
  
// Driver Code
int main()
{
    // Input
    int N = 10000;
    // Function call
    noncoprimeCountUtil(N);
  
    return 0;
}
Output:
1361

Time Complexity: O(log10N * 2 * 10 * 2 * 10). The extra factor of 10 arises as all digits [0, 9] are being iterated in each recursive call.
Auxiliary Space: O(log10N * 2 * 10 * 2)

Attention reader! Don’t stop learning now. Get hold of all the important mathematical concepts for competitive programming with the Essential Maths for CP Course at a student-friendly price. To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.




My Personal Notes arrow_drop_up
Recommended Articles
Page :