Numbers with a Fibonacci difference between Sum of digits at even and odd positions in a given range
Prerequisites: Digit DP Given a range [L, R], the task is to count the numbers in this range having the difference between, the sum of digits at even positions and sum of digits at odd positions, as a Fibonacci Number. Note: Consider the position of the least significant digit in the number as an odd position. Examples:
Input: L = 1, R = 10 Output: 1 Explanation: The only number which satisfies the given condition is 10. Input: L = 50, R = 100 Output: 27
Approach: The idea is to use the concept of Dynamic Programming to solve this problem. The concept of digit dp is used to form a DP table.
- A four-dimensional table is formed and at every recursive call, we need to check whether the required difference is a Fibonacci number or not.
- Since the highest number in the range is 1018, the maximum sum at either even or odd positions can be at max 9 times 9 and hence the maximum difference. So, we need to check only Fibonacci numbers only up to 100 at the base condition.
- To check whether the number is Fibonacci or not, generate all the Fibonacci numbers and create a hash set.
The following are the DP states of the table:
- Since we can consider our number as a sequence of digits, one state is the position at which we are currently at. This position can have values from 0 to 18 if we are dealing with the numbers up to 1018. In each recursive call, we try to build the sequence from left to right by placing a digit from 0 to 9.
- First state is the sum of the digits at even positions we have placed so far.
- Second state is the sum of the digits at odd positions we have placed so far.
- Another state is the boolean variable tight which tells the number we are trying to build has already become smaller than R so that in the upcoming recursive calls we can place any digit from 0 to 9. If the number has not become smaller, the maximum limit of digit we can place at the current position in R.
Below is the implementation of the above approach:
C++
// C++ program to count the numbers in // the range having the difference // between the sum of digits at even // and odd positions as a Fibonacci Number #include <bits/stdc++.h> using namespace std; const int M = 18; int a, b, dp[M][90][90][2]; // To store all the // Fibonacci numbers set< int > fib; // Function to generate Fibonacci // numbers upto 100 void fibonacci() { // Adding the first two Fibonacci // numbers in the set int prev = 0, curr = 1; fib.insert(prev); fib.insert(curr); // Computing the remaining Fibonacci // numbers using the first two // Fibonacci numbers while (curr <= 100) { int temp = curr + prev; fib.insert(temp); prev = curr; curr = temp; } } // Function to return the count of // required numbers from 0 to num int count( int pos, int even, int odd, int tight, vector< int > num) { // Base Case if (pos == num.size()) { if (num.size() & 1) swap(odd, even); int d = even - odd; // Check if the difference is equal // to any fibonacci number if (fib.find(d) != fib.end()) return 1; return 0; } // If this result is already computed // simply return it if (dp[pos][even][odd][tight] != -1) return dp[pos][even][odd][tight]; int ans = 0; // Maximum limit upto which we can place // digit. If tight is 1, means number has // already become smaller so we can place // any digit, otherwise num[pos] int limit = (tight ? 9 : num[pos]); for ( int d = 0; d <= limit; d++) { int currF = tight, currEven = even; int currOdd = odd; if (d < num[pos]) currF = 1; // If the current position is odd // add it to currOdd, otherwise to // currEven if (pos & 1) currOdd += d; else currEven += d; ans += count(pos + 1, currEven, currOdd, currF, num); } return dp[pos][even][odd][tight] = ans; } // Function to convert x // into its digit vector // and uses count() function // to return the required count int solve( int x) { vector< int > num; while (x) { num.push_back(x % 10); x /= 10; } reverse(num.begin(), num.end()); // Initialize dp memset (dp, -1, sizeof (dp)); return count(0, 0, 0, 0, num); } // Driver Code int main() { // Generate fibonacci numbers fibonacci(); int L = 1, R = 50; cout << solve(R) - solve(L - 1) << endl; L = 50, R = 100; cout << solve(R) - solve(L - 1) << endl; return 0; } |
Java
// Java program to count the numbers in // the range having the difference // between the sum of digits at even // and odd positions as a Fibonacci Number import java.util.*; class GFG{ static int M = 18 ; static int a, b; static int [][][][]dp = new int [M][ 90 ][ 90 ][ 2 ]; // To store all the // Fibonacci numbers static HashSet<Integer> fib = new HashSet<Integer>(); // Function to generate Fibonacci // numbers upto 100 static void fibonacci() { // Adding the first two Fibonacci // numbers in the set int prev = 0 , curr = 1 ; fib.add(prev); fib.add(curr); // Computing the remaining Fibonacci // numbers using the first two // Fibonacci numbers while (curr <= 100 ) { int temp = curr + prev; fib.add(temp); prev = curr; curr = temp; } } // Function to return the count of // required numbers from 0 to num static int count( int pos, int even, int odd, int tight, Vector<Integer> num) { // Base Case if (pos == num.size()) { if (num.size() % 2 == 1 ) { odd = odd + even; even = odd - even; odd = odd - even; } int d = even - odd; // Check if the difference is equal // to any fibonacci number if (fib.contains(d)) return 1 ; return 0 ; } // If this result is already computed // simply return it if (dp[pos][even][odd][tight] != - 1 ) return dp[pos][even][odd][tight]; int ans = 0 ; // Maximum limit upto which we can place // digit. If tight is 1, means number has // already become smaller so we can place // any digit, otherwise num[pos] int limit = (tight== 1 ? 9 : num.get(pos)); for ( int d = 0 ; d <= limit; d++) { int currF = tight, currEven = even; int currOdd = odd; if (d < num.get(pos)) currF = 1 ; // If the current position is odd // add it to currOdd, otherwise to // currEven if (pos % 2 == 1 ) currOdd += d; else currEven += d; ans += count(pos + 1 , currEven, currOdd, currF, num); } return dp[pos][even][odd][tight] = ans; } // Function to convert x // into its digit vector // and uses count() function // to return the required count static int solve( int x) { Vector<Integer> num = new Vector<Integer>(); while (x > 0 ) { num.add(x % 10 ); x /= 10 ; } Collections.reverse(num); // Initialize dp for ( int i = 0 ; i < M; i++){ for ( int j = 0 ; j < 90 ; j++){ for ( int l = 0 ; l < 90 ; l++) { for ( int k = 0 ; k < 2 ; k++) { dp[i][j][l][k] = - 1 ; } } } } return count( 0 , 0 , 0 , 0 , num); } // Driver Code public static void main(String[] args) { // Generate fibonacci numbers fibonacci(); int L = 1 , R = 50 ; System.out.print(solve(R) - solve(L - 1 ) + "\n" ); L = 50 ; R = 100 ; System.out.print(solve(R) - solve(L - 1 ) + "\n" ); } } // This code is contributed by Rajput-Ji |
Python3
# Python3 program to count the numbers in # the range having the difference # between the sum of digits at even # and odd positions as a Fibonacci Number M = 18 a = 0 b = 0 dp = [[[[ - 1 for i in range ( 2 )] for j in range ( 90 )] for k in range ( 90 )] for l in range (M)] # To store all the # Fibonacci numbers fib = set () # Function to generate Fibonacci # numbers upto 100 def fibonacci(): # Adding the first two Fibonacci # numbers in the set prev = 0 curr = 1 fib.add(prev) fib.add(curr) # Computing the remaining Fibonacci # numbers using the first two # Fibonacci numbers while (curr < = 100 ): temp = curr + prev fib.add(temp) prev = curr curr = temp # Function to return the count of # required numbers from 0 to num def count(pos,even,odd,tight,num): # Base Case if (pos = = len (num)): if (( len (num)& 1 )): val = odd odd = even even = val d = even - odd # Check if the difference is equal # to any fibonacci number if ( d in fib): return 1 return 0 # If this result is already computed # simply return it if (dp[pos][even][odd][tight] ! = - 1 ): return dp[pos][even][odd][tight] ans = 0 # Maximum limit upto which we can place # digit. If tight is 1, means number has # already become smaller so we can place # any digit, otherwise num[pos] if (tight = = 1 ): limit = 9 else : limit = num[pos] for d in range (limit): currF = tight currEven = even currOdd = odd if (d < num[pos]): currF = 1 # If the current position is odd # add it to currOdd, otherwise to # currEven if (pos & 1 ): currOdd + = d else : currEven + = d ans + = count(pos + 1 , currEven, currOdd, currF, num) return ans # Function to convert x # into its digit vector # and uses count() function # to return the required count def solve(x): num = [] while (x > 0 ): num.append(x % 10 ) x / / = 10 num = num[:: - 1 ] return count( 0 , 0 , 0 , 0 , num) # Driver Code if __name__ = = '__main__' : # Generate fibonacci numbers fibonacci() L = 1 R = 50 print (solve(R) - solve(L - 1 ) + 1 ) L = 50 R = 100 print (solve(R) - solve(L - 1 ) + 2 ) # This code is contributed by Surendra_Gangwar |
C#
// C# program to count the numbers in // the range having the difference // between the sum of digits at even // and odd positions as a Fibonacci Number using System; using System.Collections.Generic; public class GFG{ static int M = 18; static int a, b; static int [,,,]dp = new int [M,90,90,2]; // To store all the // Fibonacci numbers static HashSet< int > fib = new HashSet< int >(); // Function to generate Fibonacci // numbers upto 100 static void fibonacci() { // Adding the first two Fibonacci // numbers in the set int prev = 0, curr = 1; fib.Add(prev); fib.Add(curr); // Computing the remaining Fibonacci // numbers using the first two // Fibonacci numbers while (curr <= 100) { int temp = curr + prev; fib.Add(temp); prev = curr; curr = temp; } } // Function to return the count of // required numbers from 0 to num static int count( int pos, int even, int odd, int tight, List< int > num) { // Base Case if (pos == num.Count) { if (num.Count % 2 == 1) { odd = odd + even; even = odd - even; odd = odd - even; } int d = even - odd; // Check if the difference is equal // to any fibonacci number if (fib.Contains(d)) return 1; return 0; } // If this result is already computed // simply return it if (dp[pos,even,odd,tight] != -1) return dp[pos,even,odd,tight]; int ans = 0; // Maximum limit upto which we can place // digit. If tight is 1, means number has // already become smaller so we can place // any digit, otherwise num[pos] int limit = (tight==1 ? 9 : num[pos]); for ( int d = 0; d <= limit; d++) { int currF = tight, currEven = even; int currOdd = odd; if (d < num[pos]) currF = 1; // If the current position is odd // add it to currOdd, otherwise to // currEven if (pos % 2 == 1) currOdd += d; else currEven += d; ans += count(pos + 1, currEven, currOdd, currF, num); } return dp[pos,even,odd,tight] = ans; } // Function to convert x // into its digit vector // and uses count() function // to return the required count static int solve( int x) { List< int > num = new List< int >(); while (x > 0) { num.Add(x % 10); x /= 10; } num.Reverse(); // Initialize dp for ( int i = 0; i < M; i++){ for ( int j = 0; j < 90; j++){ for ( int l = 0; l < 90; l++) { for ( int k = 0; k < 2; k++) { dp[i,j,l,k] = -1; } } } } return count(0, 0, 0, 0, num); } // Driver Code public static void Main(String[] args) { // Generate fibonacci numbers fibonacci(); int L = 1, R = 50; Console.Write(solve(R) - solve(L - 1) + "\n" ); L = 50; R = 100; Console.Write(solve(R) - solve(L - 1) + "\n" ); } } // This code contributed by Rajput-Ji |
Javascript
// JavaScript program to count the numbers in // the range having the difference // between the sum of digits at even // and odd positions as a Fibonacci Number const M = 18; let a; let b; let dp = new Array(); for (let i = 0; i < M; i++){ dp.push( new Array()); for (let j = 0; j < 90; j++){ dp[i].push( new Array()); for (let k = 0; k < 90; k++){ dp[i][j].push( new Array()); for (let l = 0; l < 2; l++){ dp[i][j][k].push(-1); } } } } // To store all the // Fibonacci numbers let fib = new Set(); // Function to generate Fibonacci // numbers upto 100 function fibonacci() { // Adding the first two Fibonacci // numbers in the set let prev = 0; let curr = 1; fib.add(prev); fib.add(curr); // Computing the remaining Fibonacci // numbers using the first two // Fibonacci numbers while (curr <= 100) { let temp = curr + prev; fib.add(temp); prev = curr; curr = temp; } } // Function to return the count of // required numbers from 0 to num function count(pos, even, odd, tight, num) { // Base Case if (pos == num.length) { if (num.length & 1 != 0){ // Swapping the two numbers. let tmp = odd; odd = even; even = tmp; } let d = even - odd; // Check if the difference is equal // to any fibonacci number if (fib.has(d)) return 1; return 0; } // If this result is already computed // simply return it if (dp[pos][even][odd][tight] != -1) return dp[pos][even][odd][tight]; let ans = 0; // Maximum limit upto which we can place // digit. If tight is 1, means number has // already become smaller so we can place // any digit, otherwise num[pos] let limit = (tight == 1 ? 9 : num[pos]); for (let d = 0; d <= limit; d++) { let currF = tight; let currEven = even; let currOdd = odd; if (d < num[pos]) currF = 1; // If the current position is odd // add it to currOdd, otherwise to // currEven if (pos & 1 != 0) currOdd = currOdd + d; else currEven = currEven + d; ans = ans + count(pos + 1, currEven, currOdd, currF, num); } return dp[pos][even][odd][tight] = ans; } // Function to convert x // into its digit vector // and uses count() function // to return the required count function solve(x) { let num = new Array(); while (x) { num.push(x % 10); x = Math.floor(x/10); } num = num.reverse(); // Initialize dp for (let i = 0; i < M; i++){ for (let j = 0; j < 90; j++){ for (let k = 0; k < 90; k++){ for (let l = 0; l < 2; l++){ dp[i][j][k][l] = -1; } } } } return count(0, 0, 0, 0, num); } // Driver Code // Generate fibonacci numbers fibonacci(); let L = 1; let R = 50; console.log(solve(R) - solve(L - 1)); L = 50; R = 100; console.log(solve(R) - solve(L - 1)); // The code is contributed by Gautam goel (gautamgoel962) |
Output:
14 27
Please Login to comment...