Count numbers in range whose sum of digits is divisible by XOR of digits
Given integers L and R, the task for this problem is to find a number of integers in the range L to R whose sum of digits is divisible by bitwise XOR of digits. print the answer. ( L <= R <= 1018)
Note: Bitwise XOR sum zero never divides any other number.
Examples:
Input: L = 10, R = 15
Output: 4
Explanation:
- Number 10 : digitSum = 1 + 0 = 1, xorSum = 1 ^ 0 = 1, included in answer, 1 % 1 = 0
- Number 11: digitSum = 1 + 1 = 2, xorSum = 1 ^ 1 = 0, not included in answer since bitwise XOR sum is zero.
- Number 12: digitSum = 1 + 2 = 3, xorSum = 1 ^ 2 = 3, included in answer since 2 % 1 = 0
- Number 13: digitSum = 1 + 3 = 4, xorSum = 1 ^ 3 = 2, included in answer since 4 % 2 = 0
- Number 14: digitSum = 1 + 4 = 5, xorSum = 1 ^ 4 = 5, included in answer since 5 % 5 = 0
- Number 15: digitSum = 1 + 5 = 6, xorSum = 1 ^ 5 = 4, not included in answer since 6 % 4 != 0
10, 12, 13 and 14 are the numbers whose sum of digits are divisible by bitwise XOR sum of digits
Input: L = 1, R = 100
Output: 67
Naive approach: The basic way to solve the problem is as follows:
The basic way to solve this problem is to generate all possible combinations by using a recursive approach.
Time Complexity: O(18N), Where N is the number of digits to be filled.
Auxiliary Space: O(1)
Efficient Approach: Dynamic programming can be used to solve this problem:
- dp[i][j][k][l] represents numbers in the range with i digits, j represents tight condition, k represents current sum and l represents bitwise XOR sum.
- It can be observed that the recursive function is called exponential times. That means that some states are called repeatedly.
- So the idea is to store the value of each state. This can be done using by storing the value of a state and whenever the function is called, returning the stored value without computing again.
- First answer will be calculated for 0 to L – 1 and then calculated for 0 to R then the latter one is subtracted from the prior one to get answer for range [L, R].
Follow the steps below to solve the problem:
- Create a recursive function that takes four parameters i representing the position to be filled, j representing a tight condition, k representing the sum of digits, and finally l containing bitwise XOR sum of digits.
- Call the recursive function for choosing all digits from 0 to 9.
- Base case if the size of the digit is N and the sum is divisible by bitwise XOR sum return 1 else returns 0.
- Create a 4d array dp[20][2][180][16] initially filled with -1.
- If the answer for a particular state is computed then save it in dp[i][j][k][l].
- if the answer for a particular state is already computed then just return dp[i][j][k][l].
Below is the implementation of the above approach:
C++
// C++ code to implement the approach #include <bits/stdc++.h> using namespace std; // dp table initialized with -1 int dp[20][2][180][16]; // recursive Function to find numbers // in the range L to R such that digit // sum is divisible by xor sum of digits. int recur( int i, int j, int k, int l, string& a) { // Base case if (i == a.size()) { // Sum of digits is divisible by // xor of digits return 1 if (l != 0 and k % l == 0) return 1; // Otherwise return 0 else return 0; } // If answer for current state is // already calculated then just // return dp[i][j][k][l] if (dp[i][j][k][l] != -1) return dp[i][j][k][l]; // Answer initialized with zero int ans = 0; // Tight condition true if (j == 1) { // Iterating from 0 to max value // of tight condition for ( int digit = 0; digit <= (( int )a[i] - 48); digit++) { // When digit is at max tight // condition remains even in // next state if (digit == (( int )a[i] - 48)) // Calling recursive function // for tight digit ans += recur(i + 1, 1, k + digit, l ^ digit, a); // Tight condition drops else // calling recursive function // for digits less than tight // condition digit ans += recur(i + 1, 0, k + digit, l ^ digit, a); } } // Tight condition false else { // iterating for all digits for ( int digit = 0; digit <= 9; digit++) { // Calling recursive function // for all digits from 0 to 9 ans += recur(i + 1, 0, k + digit, l ^ digit, a); } } // save and return dp value return dp[i][j][k][l] = ans; } // Function to find numbers in the // range L to R such that digit sum // is divisible by xor sum of digits. int countInRange( int A, int B) { // Initializing dp array with - 1 memset (dp, -1, sizeof (dp)); A--; string L = to_string(A), R = to_string(B); // Numbers with sum of digits divisible // by xor sum of digits // in the range 0 to L int ans1 = recur(0, 1, 0, 0, L); // Initializing dp array with - 1 memset (dp, -1, sizeof (dp)); // Numbers with sum of digits divisible // by xor sum of digits // in the range 0 to R int ans2 = recur(0, 1, 0, 0, R); // Difference of ans2 and ans1 // will generate answer for // required range return ans2 - ans1; } // Driver Code int main() { // Input 1 int L = 10, R = 15; // Function Call cout << countInRange(L, R) << endl; // Input 2 int L1 = 1, R1 = 100; // Function Call cout << countInRange(L1, R1) << endl; return 0; } |
Java
// java code to implement the approach import java.io.*; import java.util.*; class GFG { // recursive Function to find numbers // in the range L to R such that digit // sum is divisible by xor sum of digits. public static int recur( int [][][][] dp, int i, int j, int k, int l, StringBuilder a) { // Base Case if (i == a.length()) { // Sum of digits is divisible by // xor of digits return 1 if (l != 0 && k % l == 0 ) return 1 ; // Otherwise return 0 else return 0 ; } // If answer for current state is // already calculated then just // return dp[i][j][k][l] if (dp[i][j][k][l] != - 1 ) return dp[i][j][k][l]; // Answer initialized with zero int ans = 0 ; // Tight condition true if (j == 1 ) { // Iterating from 0 to max value // of tight condition for ( int digit = 0 ; digit <= (( int )a.charAt(i) - 48 ); digit++) { // When digit is at max tight // condition remains even in // next state if (digit == (( int )a.charAt(i) - 48 )) // Calling recursive function // for tight digit ans += recur(dp, i + 1 , 1 , k + digit, (l ^ digit), a); // Tight condition drops else // calling recursive function // for digits less than tight // condition digit ans += recur(dp, i + 1 , 0 , k + digit, (l ^ digit), a); } } // Tight condition false else { // iterating for all digits for ( int digit = 0 ; digit <= 9 ; digit++) { // Calling recursive function // for all digits from 0 to 9 ans += recur(dp, i + 1 , 0 , k + digit, (l ^ digit), a); } } // save and return dp value return dp[i][j][k][l] = ans; } // Function to find numbers in the // range L to R such that digit sum // is divisible by xor sum of digits. public static int countInRange( int [][][][] dp, int A, int B) { // Initializing dp array with - 1 for ( int i = 0 ; i < 20 ; i++) { for ( int j = 0 ; j < 2 ; j++) { for ( int a = 0 ; a < 180 ; a++) { for ( int b = 0 ; b < 16 ; b++) { dp[i][j][a][b] = - 1 ; } } } } A--; StringBuilder L = new StringBuilder(Integer.toString(A)); StringBuilder R = new StringBuilder(Integer.toString(B)); // Numbers with sum of digits divisible // by xor sum of digits // in the range 0 to L int ans1 = recur(dp, 0 , 1 , 0 , 0 , L); // Initializing dp array with - 1 for ( int i = 0 ; i < 20 ; i++) { for ( int j = 0 ; j < 2 ; j++) { for ( int a = 0 ; a < 180 ; a++) { for ( int b = 0 ; b < 16 ; b++) { dp[i][j][a][b] = - 1 ; } } } } // Numbers with sum of digits divisible // by xor sum of digits // in the range 0 to R int ans2 = recur(dp, 0 , 1 , 0 , 0 , R); // Difference of ans2 and ans1 // will generate answer for // required range return ans2 - ans1; } // Driver Code public static void main(String[] args) { int [][][][] dp = new int [ 20 ][ 2 ][ 180 ][ 16 ]; // Input 1 int L = 10 , R = 15 ; // Function Call System.out.println(countInRange(dp, L, R)); // Input 2 int L1 = 1 , R1 = 100 ; // Function Call System.out.println(countInRange(dp, L1, R1)); } } |
Python3
# Python code to implement the approach # dp table initialized with -1 dp = [[[[ - 1 for l in range ( 16 )] for k in range ( 180 )] for j in range ( 2 )] for i in range ( 20 )] # recursive Function to find numbers # in the range L to R such that digit # sum is divisible by xor sum of digits. def recur(i, j, k, l, a): # Base case if i = = len (a): # Sum of digits is divisible by # xor of digits return 1 if l ! = 0 and k % l = = 0 : return 1 # Otherwise return 0 else : return 0 # If answer for current state is # already calculated then just # return dp[i][j][k][l] if dp[i][j][k][l] ! = - 1 : return dp[i][j][k][l] # Answer initialized with zero ans = 0 # Tight condition true if j = = 1 : # Iterating from 0 to max value # of tight condition for digit in range ( 0 , int (a[i]) + 1 ): # When digit is at max tight # condition remains even in # next state if digit = = int (a[i]): # Calling recursive function # for tight digit ans + = recur(i + 1 , 1 , k + digit, l ^ digit, a) # Tight condition drops else : # calling recursive function # for digits less than tight # condition digit ans + = recur(i + 1 , 0 , k + digit, l ^ digit, a) # Tight condition false else : # iterating for all digits for digit in range ( 0 , 10 ): # Calling recursive function # for all digits from 0 to 9 ans + = recur(i + 1 , 0 , k + digit, l ^ digit, a) # save and return dp value dp[i][j][k][l] = ans return ans # Function to find numbers in the # range L to R such that digit sum # is divisible by xor sum of digits. def countInRange(A, B): # Initializing dp array with - 1 for i in range ( 20 ): for j in range ( 2 ): for k in range ( 180 ): for l in range ( 16 ): dp[i][j][k][l] = - 1 A - = 1 L = str (A) R = str (B) # Numbers with sum of digits divisible # by xor sum of digits # in the range 0 to L ans1 = recur( 0 , 1 , 0 , 0 , L) # Initializing dp array with - 1 for i in range ( 20 ): for j in range ( 2 ): for k in range ( 180 ): for l in range ( 16 ): dp[i][j][k][l] = - 1 # Numbers with sum of digits divisible # by xor sum of digits # in the range 0 to R ans2 = recur( 0 , 1 , 0 , 0 , R) # Difference of ans2 and ans1 # will generate answer for # required range return ans2 - ans1 # Driver Code # Input 1 L = 10 R = 15 # Function Call print (countInRange(L, R)) # Input 2 L1 = 1 R1 = 100 # Function Call print (countInRange(L1, R1)) # This code is contributed by Prasad kandekar(prasad264) |
C#
// C# code to implement the approach using System; using System.Text; public class GFG { // recursive Function to find numbers // in the range L to R such that digit // sum is divisible by xor sum of digits. public static int recur( int [, , , ] dp, int i, int j, int k, int l, StringBuilder a) { // Base Case if (i == a.Length) { // Sum of digits is divisible by // xor of digits return 1 if (l != 0 && k % l == 0) return 1; // Otherwise return 0 else return 0; } // If answer for current state is // already calculated then just // return dp[i][j][k][l] if (dp[i, j, k, l] != -1) return dp[i, j, k, l]; // Answer initialized with zero int ans = 0; // Tight condition true if (j == 1) { // Iterating from 0 to max value // of tight condition for ( int digit = 0; digit <= (a[i] - 48); digit++) { // When digit is at max tight // condition remains even in // next state if (digit == (a[i] - 48)) // Calling recursive function // for tight digit ans += recur(dp, i + 1, 1, k + digit, (l ^ digit), a); // Tight condition drops else // calling recursive function // for digits less than tight // condition digit ans += recur(dp, i + 1, 0, k + digit, (l ^ digit), a); } } // Tight condition false else { // iterating for all digits for ( int digit = 0; digit <= 9; digit++) { // Calling recursive function // for all digits from 0 to 9 ans += recur(dp, i + 1, 0, k + digit, (l ^ digit), a); } } // save and return dp value return dp[i, j, k, l] = ans; } // Function to find numbers in the // range L to R such that digit sum // is divisible by xor sum of digits. public static int countInRange( int [, , , ] dp, int A, int B) { // Initializing dp array with - 1 for ( int i = 0; i < 20; i++) { for ( int j = 0; j < 2; j++) { for ( int a = 0; a < 180; a++) { for ( int b = 0; b < 16; b++) { dp[i, j, a, b] = -1; } } } } A--; StringBuilder L = new StringBuilder(A.ToString()); StringBuilder R = new StringBuilder(B.ToString()); // Numbers with sum of digits divisible // by xor sum of digits // in the range 0 to L int ans1 = recur(dp, 0, 1, 0, 0, L); // Initializing dp array with - 1 for ( int i = 0; i < 20; i++) { for ( int j = 0; j < 2; j++) { for ( int a = 0; a < 180; a++) { for ( int b = 0; b < 16; b++) { dp[i, j, a, b] = -1; } } } } // Numbers with sum of digits divisible // by xor sum of digits // in the range 0 to R int ans2 = recur(dp, 0, 1, 0, 0, R); // Difference of ans2 and ans1 // will generate answer for // required range return ans2 - ans1; } static public void Main() { // Code int [, , , ] dp = new int [20, 2, 180, 16]; // Input 1 int L = 10, R = 15; // Function Call Console.WriteLine(countInRange(dp, L, R)); // Input 2 int L1 = 1, R1 = 100; // Function Call Console.WriteLine(countInRange(dp, L1, R1)); } } // This code is contributed by lokesh. |
Javascript
// Javascript code to implement the approach // dp table initialized with -1 let dp= new Array(20); for (let i=0; i<20; i++) { dp[i]= new Array(2); for (let j=0; j<2; j++) { dp[i][j]= new Array(180); for (let k=0; k<180; k++) dp[i][j][k]= new Array(16); } } // recursive Function to find numbers // in the range L to R such that digit // sum is divisible by xor sum of digits. function recur( i, j, k, l, a) { // Base case if (i == a.length) { // Sum of digits is divisible by // xor of digits return 1 if (l != 0 && k % l == 0) return 1; // Otherwise return 0 else return 0; } // If answer for current state is // already calculated then just // return dp[i][j][k][l] if (dp[i][j][k][l] != -1) return dp[i][j][k][l]; // Answer initialized with zero let ans = 0; // Tight condition true if (j == 1) { // Iterating from 0 to max value // of tight condition for (let digit = 0; digit <= parseInt(a[i]); digit++) { // When digit is at max tight // condition remains even in // next state if (digit == parseInt(a[i])) // Calling recursive function // for tight digit ans += recur(i + 1, 1, k + digit, l ^ digit, a); // Tight condition drops else // calling recursive function // for digits less than tight // condition digit ans += recur(i + 1, 0, k + digit, l ^ digit, a); } } // Tight condition false else { // iterating for all digits for (let digit = 0; digit <= 9; digit++) { // Calling recursive function // for all digits from 0 to 9 ans += recur(i + 1, 0, k + digit, l ^ digit, a); } } // save and return dp value return dp[i][j][k][l] = ans; } // Function to find numbers in the // range L to R such that digit sum // is divisible by xor sum of digits. function countInRange( A, B) { // Initializing dp array with - 1 for (let i=0; i<20; i++) { for (let j=0; j<2; j++) { for (let k=0; k<180; k++) { for (let l=0; l<16; l++) dp[i][j][k][l]=-1; } } } A--; let L = A.toString(), R = B.toString(); // Numbers with sum of digits divisible // by xor sum of digits // in the range 0 to L let ans1 = recur(0, 1, 0, 0, L); // Initializing dp array with - 1 for (let i=0; i<20; i++) { for (let j=0; j<2; j++) { for (let k=0; k<180; k++) { for (let l=0; l<16; l++) dp[i][j][k][l]=-1; } } } // Numbers with sum of digits divisible // by xor sum of digits // in the range 0 to R let ans2 = recur(0, 1, 0, 0, R); // Difference of ans2 and ans1 // will generate answer for // required range return ans2 - ans1; } // Driver Code // Input 1 let L = 10, R = 15; // Function Call document.write(countInRange(L, R)); // Input 2 let L1 = 1, R1 = 100; // Function Call document.write(countInRange(L1, R1)); |
4 67
Time Complexity: O(log(R) * M * N), where M is the maximum sum of digits and N is the maximum bitwise XOR sum of digits
Auxiliary Space: O(log(R) * M * N)
Related Articles:
Please Login to comment...