# Fibonacci sum of a subset with all elements <= k

Given an array of n elements, the task is to find the fibonacci sum of a subset of the array where every element of the subset <= k.
Precisely, find F(Ai1) + F(Ai2) + F(Ai3) + … + F(Aix)), where (Ai1, Ai2, …, Aix) <= K and 1 <= (i1, i2, …, ix) <= n. Here, F(i) is the ith Fibonacci number

Examples :

```Input : arr = {1, 2, 3, 4, 2, 7}
Query 1 : K = 2
Query 2 : K = 6
Output : 3
8
```

Explanation :
In Query 1, the subset {1, 2, 2} is such a subset where all the elements in the subset are <= k i.e <= 2 in this case. The Fibonacci sum of the subset = F(1) + F(2) + F(2) = 1 + 1 + 1 = 3

In Query 2, the subset {1, 2, 3, 4, 2} is such a subset where all the elements in the subset are <= k i.e <= 6 in this case. The Fibonacci sum of the subset = F(1) + F(2) + F(3) + F(4) + F(2) = 1 + 1 + 2 + 3 + 1 = 8

Solve this using two different querying techniques, namely :
1) Online Querying,
2) Offline Querying

In both these methods, the only common step is the generation of the nth Fibonacci number.For an efficient technique to generate the nth Fibonacci number using this.

This method of generating the Fibonacci numbers is common to both querying techniques. Now, look at how to use these Fibonacci numbers that are generated using each of these two techniques.

Method 1 (Online Querying) :
In this technique, process the queries as they arrive. First of all, sort the array in increasing order. After getting a query for a particular k, use binary search on this sorted array to find the last index where the value of the array is & <= k. Let’s call this position x.

Now, since the array is sorted,

```For all i <= x, a[i] <= x
i.e
a[i] <= a[x] for all i ∈ [1, x]
```

So, the subset to focus at is A1, A2, A3, ….Ax in the sorted array A, and Fibonacci sum is : F(A1)+F(A2)+F(A3)+…+F(Ax)

Use Prefix sum arrays to efficiently find the sum of the subset A1, A2, A3, ….Ax.

If prefixFibSum[i] stores the Fibonacci sum till the ith index of the sorted array A, then, the Fibonacci sum of subset of the array from 1 to x, is prefixFibSum[x]

Thus, Fibonacci Sum of Subset[1…x] = prefixFibSum[x], prefixFibSum[x] can be calculated as follows :
prefixFibSum[x] = prefixFibSum[x – 1] + A[x]th Fibonacci number, where, A[x] is the array element at xth index of the array.

 `// C++ program to find fibonacci sum of  ` `// subarray where all elements <= k ` `#include ` ` `  `using` `namespace` `std; ` ` `  `// Helper function that multiplies 2 matrices ` `// F and M of size 2*2, and puts the multiplication ` `// result back to F[][] ` `void` `multiply(``int` `F, ``int` `M) ` `{ ` `    ``int` `x = F * M + F * M; ` `    ``int` `y = F * M + F * M; ` `    ``int` `z = F * M + F * M; ` `    ``int` `w = F * M + F * M; ` ` `  `    ``F = x; ` `    ``F = y; ` `    ``F = z; ` `    ``F = w; ` `} ` ` `  `/* Helper function that calculates F[][] ` `   ``raise to the power n and puts the  ` `   ``result in F[][]  */` `void` `power(``int` `F, ``int` `n) ` `{ ` `    ``int` `i; ` `    ``int` `M = { { 1, 1 }, { 1, 0 } }; ` ` `  `    ``// n - 1 times multiply the  ` `    ``// matrix to {{1, 0}, {0, 1}} ` `    ``for` `(i = 2; i <= n; i++) ` `        ``multiply(F, M); ` `} ` ` `  `// Returns the nth fibonacci number ` `int` `fib(``int` `n) ` `{ ` `    ``int` `F = { { 1, 1 }, { 1, 0 } }; ` `    ``if` `(n == 0) ` `        ``return` `0; ` `    ``power(F, n - 1); ` ` `  `    ``return` `F; ` `} ` ` `  `int` `findLessThanK(``int` `arr[], ``int` `n, ``int` `k) ` `{ ` `    ``// find first index which is > k  ` `    ``// using lower_bound ` `    ``return` `(lower_bound(arr, arr + n, k + 1)  ` `                        ``- arr); ` `} ` ` `  `// Function to build Prefix Fibonacci Sum ` `int``* buildPrefixFibonacciSum(``int` `arr[], ``int` `n) ` `{ ` `    ``// Allocate memory to prefix  ` `    ``// fibonacci sum array ` `    ``int``* prefixFibSum = ``new` `int``[n]; ` ` `  `    ``// Traverse the array from 0 to n - 1, ` `    ``// when at the ith index then we calculate  ` `    ``// the a[i]th fibonacci number and calculate ` `    ``// the fibonacci sum till the ith index as ` `    ``// the sum of fibonacci sum till index i - 1  ` `    ``// and the a[i]th fibonacci number ` `    ``for` `(``int` `i = 0; i < n; i++)  ` `    ``{ ` `        ``int` `currFibNumber = fib(arr[i]); ` `        ``if` `(i == 0) { ` `            ``prefixFibSum[i] = currFibNumber; ` `        ``} ` `        ``else` `{ ` `            ``prefixFibSum[i] = prefixFibSum[i - 1]  ` `                              ``+ currFibNumber; ` `        ``} ` `    ``} ` `    ``return` `prefixFibSum; ` `} ` ` `  `// Return the answer for each query ` `int` `processQuery(``int` `arr[], ``int` `prefixFibSum[],  ` `                 ``int` `n, ``int` `k) ` `{ ` ` `  `    ``// index stores the index till where ` `    ``// the array elements are less than k ` `    ``int` `lessThanIndex = findLessThanK(arr, n, k); ` ` `  `    ``if` `(lessThanIndex == 0) ` `        ``return` `0; ` `    ``return` `prefixFibSum[lessThanIndex - 1]; ` `} ` ` `  `// Driver Code ` `int` `main() ` `{ ` `    ``int` `arr[] = { 1, 2, 3, 4, 2, 7 }; ` `    ``int` `n = ``sizeof``(arr) / ``sizeof``(arr); ` ` `  `    ``// sort the array arr ` `    ``sort(arr, arr + n); ` ` `  `    ``// Build the prefix fibonacci sum array ` `    ``int``* prefixFibSum =  ` `         ``buildPrefixFibonacciSum(arr, n); ` ` `  `    ``// query array stores q queries ` `    ``int` `query[] = { 2, 6 }; ` `    ``int` `q = ``sizeof``(query) / ``sizeof``(query); ` ` `  `    ``for` `(``int` `i = 0; i < q; i++) { ` `        ``int` `k = query[i]; ` `        ``int` `ans =  ` `            ``processQuery(arr, prefixFibSum, n, k); ` `         `  `        ``cout << ``"Query  "` `<< i + 1 << ``" : "` `             ``<< ans << endl; ` `    ``} ` `    ``return` `0; ` `} `

Output:

```Query  1 : 3
Query  2 : 8
```

Time Complexity : O(nlogn + qlogn)

Method 2 (Offline Querying) :
In offline querying, store the queries and calculate the answer for each query in a specific order and store and output the result of the queries in the original specified order.

Store each query as a pair of integers where the first member of the pair is the query parameter K for that query and the second member of the pair is the index at which the query occurs originally.
E.g. If queries are following :
query 1 : K = 13;
query 2 : K = 3;
query 3 : K = 8;
then, store query 1 as where 13 is the value of K for that query and 1 is the index specifying that it is the 1st query, similarly query 2 and query 3 are represented as and respectively.

Once, all individual queries are represented as pairs of integers sort the array of query pairs on the basis on K in increasing fashion.
E.g. the above queries after sorting will look like {,, }.

Idea behind sorting queries :
The main idea behind sorting the queries is that when there are elements of a subset which are less than k for some query qi then for all queries qj where i < j and thus Ki <= Kj these elements are present so if the array of elements and the queries(sorted by K) both are sorted, then maintain two pointers one on the array and the other on the queries array.

i, pointing to ith index of the array,
j, pointing to jth index of the queries array

Then, consider the following Pseudo Code :

```while (i <= query[j].K) {
fibonacciSum  = fibonacciSum + a[i]th Fibonacci number
i = i + 1
}
```

So, while the elements in the subset are less than or equal to the current query pair’s first member (i.e K), keep on advancing to the next element while adding the required Fibonacci number to the current sum. Once the current element becomes greater than the parameter K of the current query store the current value of sum in the auxiliary array named ans of size q (i.e number of queries) at the index pointed by the 2nd member of the current query’s pair (i.e the original index at which the current query occurs).

```ans[query[j].original index] = current value of fibonacciSum
```

At the end, print the ans array, which stores the result of all the queries in the order in which they were originally present.

 `// C++ program to find fibonacci sum of  ` `// subarray where all elements <= k ` `#include ` ` `  `using` `namespace` `std; ` ` `  `// structure where K is the query parameter ` `// and original index is the index where the  ` `// query was originally present at. ` `struct` `offlineQuery { ` `    ``int` `K, originalIndex; ` `}; ` ` `  `// function tp compare queries ` `bool` `cmp(offlineQuery q1, offlineQuery q2) ` `{ ` `    ``return` `q1.K < q2.K; ` `} ` ` `  `/* Helper function that multiplies 2 matrices ` `  ``F and M of size 2*2, and puts the multiplication  ` `  ``result back to F[][] */` `void` `multiply(``int` `F, ``int` `M) ` `{ ` `    ``int` `x = F * M + F * M; ` `    ``int` `y = F * M + F * M; ` `    ``int` `z = F * M + F * M; ` `    ``int` `w = F * M + F * M; ` ` `  `    ``F = x; ` `    ``F = y; ` `    ``F = z; ` `    ``F = w; ` `} ` ` `  `/* Helper function that calculates F[][] raise ` `   ``to the power n and puts the result in F[][]  */` `void` `power(``int` `F, ``int` `n) ` `{ ` `    ``int` `i; ` `    ``int` `M = { { 1, 1 }, { 1, 0 } }; ` ` `  `    ``// n - 1 times multiply the  ` `    ``// matrix to {{1, 0}, {0, 1}} ` `    ``for` `(i = 2; i <= n; i++) ` `        ``multiply(F, M); ` `} ` ` `  `// Returns the nth fibonacci number ` `int` `fib(``int` `n) ` `{ ` `    ``int` `F = { { 1, 1 }, { 1, 0 } }; ` `    ``if` `(n == 0) ` `        ``return` `0; ` `    ``power(F, n - 1); ` ` `  `    ``return` `F; ` `} ` ` `  `// Return the answer for each query ` `int``* processQuery(``int` `arr[], ``int` `queries[],  ` `                  ``int` `n, ``int` `q) ` `{ ` `    ``// build offline queries where each query ` `    ``// is of type offlineQuery which stores ` `    ``// both K and original Index of the query ` `    ``// in the queries array ` `    ``offlineQuery* offlineQueries =  ` `                  ``new` `offlineQuery[q]; ` ` `  `    ``// Allocate memory to store ans of each query ` `    ``int``* ans = ``new` `int``[q]; ` ` `  `    ``for` `(``int` `i = 0; i < q; i++) { ` `        ``int` `original_index = i; ` `        ``int` `K = queries[i]; ` `        ``offlineQueries[i].K = K; ` `        ``offlineQueries[i].originalIndex =  ` `                          ``original_index; ` `    ``} ` ` `  `    ``// sort offlineQueries[] ` `    ``sort(offlineQueries, offlineQueries + q, cmp); ` ` `  `    ``// i is pointing to the current position ` `    ``// array arr fibonacciSum store the  ` `    ``// fibonacciSum till ith index ` `    ``int` `i = 0, fibonacciSum = 0; ` `     `  `    ``for` `(``int` `j = 0; j < q; j++)  ` `    ``{ ` `        ``int` `currK = offlineQueries[j].K; ` `        ``int` `currQueryIndex =  ` `            ``offlineQueries[j].originalIndex; ` ` `  `        ``// keep insering elements to subset ` `        ``// while elements are less than  ` `        ``// current query's K value ` `        ``while` `(i < n && arr[i] <= currK)  ` `        ``{ ` `            ``fibonacciSum += fib(arr[i]); ` `            ``i++; ` `        ``} ` ` `  `        ``// store the current value of ` `        ``// fibonacci sum in the array ans ` `        ``// which stores results for the ` `        ``// queries in the original order ` `        ``ans[currQueryIndex] = fibonacciSum; ` `    ``} ` ` `  `    ``return` `ans; ` `} ` ` `  `// Driver Code ` `int` `main() ` `{ ` `    ``int` `arr[] = { 1, 2, 3, 4, 2, 7 }; ` `    ``int` `n = ``sizeof``(arr) / ``sizeof``(arr); ` ` `  `    ``// sort the array arr ` `    ``sort(arr, arr + n); ` ` `  `    ``// query array stores q queries ` `    ``int` `queries[] = { 2, 10, 6 }; ` `    ``int` `q = ``sizeof``(queries) / ``sizeof``(queries); ` ` `  `    ``// res stores the result of each query ` `    ``int``* res = processQuery(arr, queries, n, q); ` ` `  `    ``for` `(``int` `i = 0; i < q; i++) { ` `        ``int` `ans = res[i]; ` `        ``cout << ``"Query  "` `<< i + 1 << ``" : "` `             ``<< ans << endl; ` `    ``} ` `    ``return` `0; ` `} `

Output:

```Query  1 : 3
Query  2 : 21
Query  3 : 8
```

Time Complexity : O(nlogn + qlogq)

My Personal Notes arrow_drop_up Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.