Count of ways in which N can be represented as sum of Fibonacci numbers without repetition - GeeksforGeeks

18 Jan, 2022
Given a number N, the task is to find the number of ways in which the integer N can be represented as a sum of Fibonacci numbers without repetition of any Fibonacci number. 
Examples:
Input: N = 13Output: 3Explanation: The possible ways to select N as 13 are: {13} {8, 5} {8, 3, 2}. Note that it is not possible to select {5 + 5 + 3} because 5 appears twice.
Input: N = 87Output: 5Explanation:The possible ways to select N as 13 are: {55 + 21 + 8 + 3}, {55 + 21 + 8 + 2 + 1}, {55 + 21 + 5 + 3 + 2 + 1}, {55 + 13 + 8 + 5 + 3 + 2 + 1}, {34 + 21 + 13 + 8 + 5 + 3 + 2 + 1}.
Naive Approach: The naive idea is to write all the possible combinations that add up to given number N. Check if any combination has repeated integers then don’t increase the counter otherwise increase the count by 1 each time. Return the count at the end.
Time Complexity: O(N)Auxiliary Space: O(1)
Efficient Approach: The idea is to use Dynamic Programming to optimize the above approach. Below are the steps:
Let us represent a number in the Fibonacci code.
Imagine Fibonacci coding by following way: the i-th bit of number corresponds to the i-th Fibonacci number. For Example: 16 = 13 + 3 will be written as 100100.
Write Fibonacci Code for every positive number such that no two adjacent bit is 1.
This is true for all numbers because if there are two adjacent bits are 1-bits then we can transform it into a single 1-bit by property of Fibonacci number. Let’s call this representation as canonical representation.
Get the Canonical Representation. Generate several Fibonacci numbers (about 90) and after that try to subtract all of them in the decreasing order.
Let’s store positions of 1-bits of the canonical representation of a given number into an array v in the increasing order and decompose any 1-bits into two 1-bits as follows:
Starting canonical representation:                                              1000000001After decomposing leftmost 1-bit into two smaller 1-bits:           0110000001After decomposing 2’nd leftmost 1-bit into two smaller 1-bits:   0101100001 After decomposing 3’rd leftmost 1-bit into two smaller 1-bits:   0101011001After decomposing 4’th leftmost 1-bit into two smaller 1-bits:   0101010111 
After a number of such operations, we will get the next 1-bit(or the end of the number). This 1-bit also can be decomposed, but it can be shifted by only one bit.
Initialize a dp array dp1[], dp1[i] is a number of ways to represent a number that consists of i leftmost 1-bits of the number for the case where all the remaining 1-bits are not decomposed. Also, take dp2[i] which marks the number of ways to represent a number that consists of i leftmost 1-bits of the number for the case where all the remaining 1-bits are decomposed.
For Example: N = 87
Canonical form of N = 101010100  Other 4 possible representations of N are 101010011, 101001111, 100111111, 011111111
Below is the illustration of the same:
Hence, the answer is dp1[cnt] + dp2[cnt], where cnt is the total number of 1-bits in the canonical representation. 
Below is the implementation of the above approach:
C++
Java
Python3
C#
Javascript
// C++ program for the above approach #include <bits/stdc++.h>using namespace std; long long fib[101], dp1[101];long long dp2[101], v[101]; // Function to generate the// fibonacci numbervoid fibonacci(){    // First two number of    // fibonacci sequence    fib[1] = 1;    fib[2] = 2;     for (int i = 3; i <= 87; i++) {        fib[i] = fib[i - 1] + fib[i - 2];    }} // Function to find maximum ways to// represent num as the sum of// fibonacci numberint find(int num){    int cnt = 0;     // Generate the Canonical form    // of given number    for (int i = 87; i > 0; i--) {        if (num >= fib[i]) {            v[cnt++] = i;            num -= fib[i];        }    }     // Reverse the number    reverse(v, v + cnt);     // Base condition of dp1 and dp2    dp1[0] = 1;    dp2[0] = (v[0] - 1) / 2;     // Iterate from 1 to cnt    for (int i = 1; i < cnt; i++) {         // Calculate dp1[]        dp1[i] = dp1[i - 1] + dp2[i - 1];         // Calculate dp2[]        dp2[i] = ((v[i] - v[i - 1]) / 2)                     * dp2[i - 1]                 + ((v[i] - v[i - 1] - 1) / 2)                       * dp1[i - 1];    }     // Return final ans    return (dp1[cnt - 1] + dp2[cnt - 1]);} // Driver Codeint main(){    // Function call to generate the    // fibonacci numbers    fibonacci();     // Given Number    int num = 13;     // Function Call    cout << find(num);    return 0;}
// Java program for the above approachimport java.util.*; class GFG{ static long[] fib = new long[101];static long[] dp1 = new long[101];static long[] dp2 = new long[101];static long[] v = new long[101]; // Function to generate the// fibonacci numberstatic void fibonacci(){         // First two number of    // fibonacci sequence    fib[1] = 1;    fib[2] = 2;     for(int i = 3; i <= 87; i++)    {        fib[i] = fib[i - 1] + fib[i - 2];    }} // Function to find maximum ways to// represent num as the sum of// fibonacci numberstatic long find(int num){    int cnt = 0;     // Generate the Canonical form    // of given number    for(int i = 87; i > 0; i--)    {        if (num >= fib[i])        {            v[cnt++] = i;            num -= fib[i];        }    }     // Reverse the number    for(int i = 0; i < cnt / 2; i++)    {        long t = v[i];        v[i] = v[cnt - i - 1];        v[cnt - i - 1] = t;    }         // Base condition of dp1 and dp2    dp1[0] = 1;    dp2[0] = (v[0] - 1) / 2;     // Iterate from 1 to cnt    for(int i = 1; i < cnt; i++)    {                 // Calculate dp1[]        dp1[i] = dp1[i - 1] + dp2[i - 1];         // Calculate dp2[]        dp2[i] = ((v[i] - v[i - 1]) / 2) *                 dp2[i - 1] +                 ((v[i] - v[i - 1] - 1) / 2) *                 dp1[i - 1];    }     // Return final ans    return (dp1[cnt - 1] + dp2[cnt - 1]);} // Driver codepublic static void main (String[] args){         // Function call to generate the    // fibonacci numbers    fibonacci();         // Given number    int num = 13;         // Function call    System.out.print(find(num));}} // This code is contributed by offbeat
# Python3 program for the above approachfib = [0] * 101dp1 = [0] * 101dp2 = [0] * 101v = [0] * 101 # Function to generate the# fibonacci numberdef fibonacci():     # First two number of    # fibonacci sequence    fib[1] = 1    fib[2] = 2     for i in range(3, 87 + 1):        fib[i] = fib[i - 1] + fib[i - 2] # Function to find maximum ways to# represent num as the sum of# fibonacci numberdef find(num):     cnt = 0     # Generate the Canonical form    # of given number    for i in range(87, 0, -1):        if(num >= fib[i]):            v[cnt] = i            cnt += 1            num -= fib[i]     # Reverse the number    v[::-1]     # Base condition of dp1 and dp2    dp1[0] = 1    dp2[0] = (v[0] - 1) // 2     # Iterate from 1 to cnt    for i in range(1, cnt):         # Calculate dp1[]        dp1[i] = dp1[i - 1] + dp2[i - 1]         # Calculate dp2[]        dp2[i] = (((v[i] - v[i - 1]) // 2) *                  dp2[i - 1] +                  ((v[i] - v[i - 1] - 1) // 2) *                  dp1[i - 1])     # Return final ans    return dp1[cnt - 1] + dp2[cnt - 1] # Driver Code # Function call to generate the# fibonacci numbersfibonacci() # Given numbernum = 13 # Function callprint(find(num)) # This code is contributed by Shivam Singh
// C# program for the above approachusing System; class GFG{ static long[] fib = new long[101];static long[] dp1 = new long[101]; static long[] dp2 = new long[101];static long[] v = new long[101];    // Function to generate the // fibonacci number static void fibonacci() {         // First two number of     // fibonacci sequence     fib[1] = 1;     fib[2] = 2;        for(int i = 3; i <= 87; i++)    {         fib[i] = fib[i - 1] + fib[i - 2];     } }    // Function to find maximum ways to // represent num as the sum of // fibonacci number static long find(long num) {     int cnt = 0;        // Generate the Canonical form     // of given number     for(int i = 87; i > 0; i--)     {         if (num >= fib[i])        {             v[cnt++] = i;             num -= fib[i];         }     }        // Reverse the number     for(int i = 0; i < cnt / 2; i++)    {         long t = v[i];         v[i] = v[cnt - i - 1];         v[cnt - i - 1] = t;     }           // Base condition of dp1 and dp2     dp1[0] = 1;     dp2[0] = (v[0] - 1) / 2;        // Iterate from 1 to cnt     for(int i = 1; i < cnt; i++)    {                    // Calculate dp1[]         dp1[i] = dp1[i - 1] + dp2[i - 1];            // Calculate dp2[]         dp2[i] = ((v[i] - v[i - 1]) / 2) *                  dp2[i - 1] +                 ((v[i] - v[i - 1] - 1) / 2) *                  dp1[i - 1];     }        // Return final ans     return (dp1[cnt - 1] + dp2[cnt - 1]); }  // Driver codestatic void Main(){         // Function call to generate the     // fibonacci numbers     fibonacci();            // Given number     int num = 13;            // Function call     Console.Write(find(num));}} // This code is contributed by divyeshrabadiya07
<script> // Javascript program for the above approachvar fib = Array(101).fill(0);var dp1 = Array(101).fill(0);var dp2 = Array(101).fill(0);var v = Array(101).fill(0); // Function to generate the// fibonacci numberfunction fibonacci(){         // First two number of    // fibonacci sequence    fib[1] = 1;    fib[2] = 2;     for(i = 3; i <= 87; i++)    {        fib[i] = fib[i - 1] + fib[i - 2];    }} // Function to find maximum ways to// represent num as the sum of// fibonacci numberfunction find(num){    var cnt = 0;         // Generate the Canonical form    // of given number    for(i = 87; i > 0; i--)    {        if (num >= fib[i])        {            v[cnt++] = i;            num -= fib[i];        }    }     // Reverse the number    for(i = 0; i < cnt / 2; i++)    {        var t = v[i];        v[i] = v[cnt - i - 1];        v[cnt - i - 1] = t;    }     // Base condition of dp1 and dp2    dp1[0] = 1;    dp2[0] = parseInt((v[0] - 1) / 2);     // Iterate from 1 to cnt    for(i = 1; i < cnt; i++)    {                 // Calculate dp1        dp1[i] = dp1[i - 1] + dp2[i - 1];         // Calculate dp2        dp2[i] = parseInt((v[i] - v[i - 1]) /                           2) * dp2[i - 1] +                 parseInt((v[i] - v[i - 1] - 1) /                           2) * dp1[i - 1];    }     // Return final ans    return (dp1[cnt - 1] + dp2[cnt - 1]);} // Driver code // Function call to generate the// fibonacci numbersfibonacci(); // Given numbervar num = 13; // Function calldocument.write(find(num)); // This code is contributed by todaysgaurav </script>
3
 
Time Complexity: O(log N)Auxiliary Space: O(log N)
SHIVAMSINGH67
offbeat
divyeshrabadiya07
todaysgaurav
kk9826225
Algorithms-Dynamic Programming
Fibonacci
Maths
Combinatorial
Dynamic Programming
Mathematical
Dynamic Programming
Mathematical
Fibonacci
Combinatorial
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Ways to sum to N using Natural Numbers up to K with repetitions allowed
Combinations with repetitions
Generate all possible combinations of K numbers that sums to N
Largest substring with same Characters
Generate all possible combinations of at most X characters from a given array
Largest Independent Set Problem | DP-26
Word Wrap Problem | DP-19
Partition problem | DP-18
Sieve of Eratosthenes
Maximum Length Chain of Pairs | DP-20