Open In App

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

Last Updated : 14 Jun, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

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;
}


Java




import java.util.*;
 
class GFG{
 
static int [][][][]dp = new int[100][2][10][2];
static int __gcd(int a, int b) 
    return b == 0? a:__gcd(b, a % b);    
}
// Function to count numbers whose
// adjacent digits are not co-prime
static int noncoprimeCount(int i, int N, char []S,
                    int bound, int prev,
                    int 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!=0 ? (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!=0
                                 & (j == (S[i] - '0'))?1:0,
                j,
                (allZeros!=0 & (j == 0))?1:0);
        }
    }
 
    // Return the total
    // possible valid numbers
    return val = cnt;
}
 
// Function to count numbers whose
// adjacent digits are not co-prime
static void noncoprimeCountUtil(int R)
{
    // Convert R to String.
    String S = String.valueOf(R);
 
    // Length of String
    int N = S.length();
 
    // Initialize dp array with -1
    for (int i = 0; i < 100; i++)
         for (int j = 0; j < 2; j++)
             for (int k = 0; k < 10; k++)
                 for (int l = 0; l < 2; l++)
                     dp[i][j][k][l] = -1;
 
    // Function call with initial values of
    // bound, allZeros, previous as 1, 1, 0
    int ans = noncoprimeCount(0, N, S.toCharArray(), 1, 0, 1);
 
    // Subtract 1 from the answer, as 0 is included
    System.out.print(ans - 1 +"\n");
}
 
// Driver Code
public static void main(String[] args)
{
    // Input
    int N = 10000;
    // Function call
    noncoprimeCountUtil(N);
 
}
}
 
// This code contributed by shikhasingrajput


Python3




# importing "math" for mathematical operations
import math
 
dp = []
 
# Function to count numbers whose
# adjacent digits are not co-prime
def noncoprimeCount(i, N, S,
                    bound, prev, allZeros):
    # Base Case
    # If the entire string
    # is traversed
    if (i == N):
        return 1
    val = dp[i][bound][prev][allZeros]
 
    # if the subproblem has
    # already been computed
    if (val != -1):
        return val
 
    cnt = 0
    limit = 9
    if(bound != 0):
        limit = ord(S[i])-48
    limit += 1
    for j in range(0, limit):
 
        # A digit can be placed at
        # the current position if:
 
        # GCD of current and previous
        # digits is not equal to 1
        if ((math.gcd(j, prev) != 1)
 
            # Current position is 0
            or (i == 0)
 
            # All encountered digits
            # until now are 0s
                or allZeros == 1):
 
            cnt += noncoprimeCount(
                i + 1, N, S, bound
                & (j == (ord(S[i]) - 48)),
                j,
                allZeros & (j == 0))
 
    # Return the total
    # possible valid numbers
    val = cnt
    return val
 
# Function to count numbers whose
# adjacent digits are not co-prime
def noncoprimeCountUtil(R):
   
    # Convert R to string.
    S = str(R)
 
    # Length of string
    N = len(S)
 
    # Initialize dp array with -1
    for i in range(0, 100):
        dp.append([])
        for j in range(0, 2):
            dp[i].append([])
            for k in range(0, 10):
                dp[i][j].append([])
                for l in range(0, 2):
                    dp[i][j][k].append(-1)
 
    # Function call with initial values of
    # bound, allZeros, previous as 1, 1, 0
    ans = noncoprimeCount(0, N, S, 1, 0, 1)
 
    # Subtract 1 from the answer, as 0 is included
    print(ans-1)
 
# Driver Code
# Input
N = 10000
 
# Function call
noncoprimeCountUtil(N)
 
# This code is contributed by rj13to.


C#




using System;
 
class GFG{
 
static int[,,,] dp = new int[100, 2, 10, 2];
 
static int __gcd(int a, int b)
{
    return b == 0 ? a : __gcd(b, a % b);
}
 
// Function to count numbers whose
// adjacent digits are not co-prime
static int noncoprimeCount(int i, int N, char[] S, int bound,
                           int prev, int 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 != 0 ? (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 != 0 &
                                  (j == (S[i] - '0')) ? 1 : 0, j,
                           (allZeros != 0 & (j == 0)) ? 1 : 0);
        }
    }
 
    // Return the total
    // possible valid numbers
    return val = cnt;
}
 
// Function to count numbers whose
// adjacent digits are not co-prime
static void noncoprimeCountUtil(int R)
{
     
    // Convert R to String.
    String S = String.Join("", R);
 
    // Length of String
    int N = S.Length;
 
    // Initialize dp array with -1
    for(int i = 0; i < 100; i++)
        for(int j = 0; j < 2; j++)
            for(int k = 0; k < 10; k++)
                for(int l = 0; l < 2; l++)
                    dp[i, j, k, l] = -1;
 
    // Function call with initial values of
    // bound, allZeros, previous as 1, 1, 0
    int ans = noncoprimeCount(0, N, S.ToCharArray(), 1, 0, 1);
 
    // Subtract 1 from the answer, as 0 is included
    Console.Write(ans - 1 + "\n");
}
 
// Driver Code
public static void Main(String[] args)
{
     
    // Input
    int N = 10000;
     
    // Function call
    noncoprimeCountUtil(N);
}
}
 
// This code is contributed by umadevi9616


Javascript




// Javascript code to implement the approach
 
  var dp = new Array(100)
 
  // Function for converting
  // bool to Int (True -> 1, False -> 0)
  function boolToInt(x){
      if(x){
          return 1
      }
      return 0
  }
 
  // Function for finding gcd of two numbers
  function __gcd(x, y) {
      x = Math.abs(x);
      y = Math.abs(y);
      while(y) {
        var t = y;
        y = x % y;
        x = t;
      }
      return x;
  }
 
 
  // Function to count numbers whose
  // adjacent digits are not co-prime
  function noncoprimeCount(i, N, S, bound, prev, allZeros)
  {
      // Base Case
      // If the entire string
      // is traversed
      if (i == N){
          return 1
      }
 
      var val = dp[i][bound][prev][allZeros]
 
      // If the subproblem has
      // already been computed
      if (val != -1){
          return val
      }
 
      var cnt = 0;
 
      for (let j = 0 ; j <= (bound == 1 ? (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 & boolToInt(j == (S[i] - '0')), j, allZeros & boolToInt(j == 0));
          }
      }
 
      dp[i][bound][prev][allZeros] = cnt
      // Return the total
      // possible valid numbers
      return cnt;
  }
 
  // Function to count numbers whose
  // adjacent digits are not co-prime
  function noncoprimeCountUtil(R)
  {
      // Convert R to string.
      var S = R.toString()
 
      // Length of string
      var N = S.length
 
      // Initialize dp array with -1
      for(let i = 0 ; i < 100 ; i++){
          dp[i] = new Array(2)
          for(let j = 0 ; j < 2 ; j++){
              dp[i][j] = new Array(10)
              for(let k = 0 ; k < 10 ; k++){
                  dp[i][j][k] = new Array(2)
                  for(let l = 0 ; l < 2 ; l++){
                      dp[i][j][k][l] = -1
                  }
              }
          }
      }
 
      // Function call with initial values of
      // bound, allZeros, previous as 1, 1, 0
      var ans = noncoprimeCount(0, N, S, 1, 0, 1);
 
      // Subtract 1 from the answer, as 0 is included
      console.log(ans - 1)
  }
 
  // Input
  var N = 10000;
  // Function call
  noncoprimeCountUtil(N);
   
  // This code is contributed by subhamgoyal2014.


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)

 



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads