Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
Given a series
Fib(1) * Fib (n+2) + Fib(2) * Fib(n+1) + Fib(3) * Fib(n) + ...... + Fib(n-1) * Fib(4)
or Summation Fib(x) * Fib (n-x+3) where x varies from 1 to n-1
where Fib(n) is nth number of Fibonacci series
to evaluate this series Fib(n) can be calculated using matrix exponentiation .
But the complexity for this is logn and for the n terms it would be nlogn .
I want this series to get reduced to a single term or some other optimization to improve *the time complexity .*
Any suggestions ??
I can't reduce the sum to a single term, but it can be reduced to a sum of five terms, which reduces the complexity to O(log n) arithmetic operations.
However, Fib(n) has Θ(n) bits, so the number of bit-operations is not logarithmic. There is a multiplication of a number the size of Fib(n) with n-1, so the number of bit-operations is M(n,log n), where M(a,b) is the bit-operation complexity of a multiplication of an a-bit number with a b-bit number. For the naive algorithm, M(a,b) = a*b, so the number of bit-operations in the below algorithm is O(n*log n).
The fact that allows this reduction is that Fibonacci numbers (like all numbers in a sequence defined by a linear recurrence) can be written as the sum of pure exponential terms, in particular
Fib(n) = (α^n - β^n) / (α - β)
where
α = (1 + √5)/2; β = (1 - √5)/2.
In addition to the Fibonacci numbers, I also use the Lucas numbers, which follow the same recurrence as the Fibonacci numbers,
Luc(n) = α^n + β^n
so the sequence of Lucas numbers (starting from index 0) begins with
2 1 3 4 7 11 18 29 47 ...
The relation Luc(n) = Fib(n+1) + Fib(n-1) allows an easy conversion between Fibonacci and Lucas numbers, and computation of Luc(n) in O(log n) steps can reuse the Fibonacci code.
So with the representation of Fibonacci numbers given above, we find
(α - β)^2 * Fib(k) * Fib(n+3-k) = (α^k - β^k) * (α^(n+3-k) - β^(n+3-k))
= α^(n+3) + β^(n+3) - (α^k * β^(n+3-k)) - (α^(n+3-k) * β^k)
= Luc(n+3) - ((-1)^k * α^(2k) * β^(n+3)) - ((-1)^k * α^(n+3) * β^(2k))
using the relation α * β = -1.
Now, since α - β = √5 the summation k = 1, ..., n-1 yields
n-1 n-1 n-1
5 * ∑ Fib(k)*Fib(n+3-k) = (n-1)*Luc(n+3) - β^(n+3) * ∑ (-α²)^k - α^(n+3) * ∑ (-β²)^k
k=1 k=1 k=1
The geometric sums can be written in closed form, and a bit of juggling yields the formula
n-1
∑ Fib(k)*Fib(n+3-k) = [5*(n-1)*Luc(n+3) + Luc(n+2) + 2*Luc(n+1) - 2*Luc(n-3) + Luc(n-4)]/25
k=1
Steps to follow:
Define std::vector<int> and fill it with all fibonacci numbers which you need. Compute these numbers using dynamic programming; that is, make use of results which you already have computed. Don't compute the same value more than once!
Once you have the vector filled with all the numbers you need, apply the formula Fib(x) * Fib (n-x+3) in a loop and compute the sum of the products.
assuming f(n)=f(n-1)+f(n-2) for n>2 and f(1)=f(2)=1, f(0)=0
Let E(n)=sum(k=1 .. n-1, f(k)f(n-k+3)) and E'(n)=sum(k=0 .. n, f(k)f(n-k))
Clearly E(n)=E'(n+3) - ( f(0)f(n+3) + f(n)f(3) + f(n+1)f(2) + f(n+2)f(1) + f(n+3)f(0) )
On wolfram you'll find : E'(n)= (nL(n)-f(n))/5, with L(n)=f(n+1)+f(n-1)
from this :
5E(n)=(n+3)( f(n+4)+f(n+2) ) - 5(2f(n) + f(n+1) +f(n+2))
5E(n)=(n+3)( 4f(n+1)+3f(n) ) - 10f(n+1) -15f(n)
5E(n)= (4n+2)f(n+1) + (3n-6)f(n)
Should be simple to evaluate, the complexity should be the same as the fibonnaci algorithm used,
If I know what a Lucas number is, then I can use the identity...
F(n)*F(m) = [L(m+n) - (-1)^n*L(m-n)]/5
See this reduces the sum of products of Fibonacci numbers into a sum of Lucas numbers.
Even better, since n+m is constant for each term, the sum reduces further. There are n-1 terms in this sum, so the sum reduces to a sum of Lucas numbers.
[(n-1)*L(n+3) + L(n+1) - L(n-1) + L(n-3) - ... + (-1)^(n-1)*L(5-n)]/5
As a test, for n = 5, I get 40, which is consistent with the direct sum of products:
1*13 + 1*8 + 2*5 + 3*3 = 40
For n = 1000, I get a sum of:
82283375600539014079871356568026158421560221654785733943009487102720
211767741849325389562067921531531130739623611293922046989610820831567088
516047002196966545744637588824274730947688693969572937880383134671205375
Even better, some extra work will let that sum of Lucas numbers contract further since the Lucas numbers of negative index have a simple relation to those with positive index.
As far as computing the k'th Lucas (as well as the k'th Fibonacci) number, it can be done quite efficiently as shown here.
Related
(beginner here)
I want to know how to find n-th number of the sequence F[n]=F[n-1]+F[n-2].
Input:
F[0] = a;
F[1] = b;
a,b < 101
N < 1000000001
M < 8; M=10^M;
a and b are starting sequence numbers.
n is the n-th number of the sequence i need to find.
M is modulo, the number gets very large quickly so F[n]=F[n]%10^M, we find the remainder, because only last digits of the n-th number are needed
The recursive approach is too slow:
int fib(int n)
{
if (n <= 1)
return n;
return fib(n-1) + fib(n-2);
}
The dynamic programming solution which takes O(n) time is also too slow:
f[i] = f[i-1] + f[i-2];
While there are solutions on how to find n-th number faster if first numbers of the sequence are 0 and 1 (n-th number can be found in O(log n)) by using this formula:
If n is even then k = n/2:
F(n) = [2*F(k-1) + F(k)]*F(k)
If n is odd then k = (n + 1)/2
F(n) = F(k)*F(k) + F(k-1)*F(k-1)
(link to formula and code implementation with it: https://www.geeksforgeeks.org/program-for-nth-fibonacci-number/)
But this formula does not work if starting numbers are something like 25 and 60. And the recursive approach is too slow.
So I want to know how can I find the n-th number of a sequence faster than O(n). Partial code would be helpful.
Thank you.
This matrix:
A = / 1 1 \
\ 1 0 /
When multiplied by the column vector (fn+1, fn), where fn is the nth number in a Fibonacci sequence, will give you the column vector (fn+2, fn+1), i.e. it will advance you by one step. This works no matter what the initial elements of the sequence were.
For example:
/ 1 1 \ / 8 \ = / 13 \
\ 1 0 / \ 5 / \ 8 /
So the nth fibonacci number is the first element of An-1v, where v is a column vector containing f1 and f0, the first two numbers in your sequence.
Therefore, if you can quickly calculate An-1 modulo some number, this will give you fn. This can be done using Exponentiation by squaring, which works in O(logn). Just make sure to perform the modulo after every multiplication and addition to prevent the numbers from getting too big.
I'm trying to understand recurrence relations. I've found a way to determine the maximum element in an array of integers through recursion. Below is the function. The first time it is called, n is the size of the array.
int ArrayMax(int array[], int n) {
if(n == 1)
return array[0];
int result = ArrayMax(array, n-1);
if(array[n-1] > result)
return array[n-1];
else
return result;
}
Now I want to understand the recurrence relation and how to get to big-O notation from there. I know that T(n) = aT(n/b) + f(n), but I don't see how to get what a and b should be.
a is "how many recursive calls there are", and b is "how many pieces you split the data into", intuitively. Note that the parameter inside the recursive call doesn't have to be n divided by something, in general it's any function of n that describes how the magnitude of your data has been changed.
For example binary search does one recursive call at each layer, splits the data into 2, and does constant work at each layer, so it has T(n) = T(n/2) + c. Merge sort splits the data in two each time (the split taking work proportional to n) and recurses on both subarrays - so you get T(n) = 2T(n/2) + cn.
In your example, you'd have T(n) = T(n-1) + c, as you're making one recursive call and "splitting the data" by reducing its size by 1 each time.
To get the big O notation from this, you just make substitutions or expand. With your example it's easy:
T(n) = T(n-1) + c = T(n-2) + 2c = T(n-3) + 3c = ... = T(0) + nc
If you assume T(0) = c0, some "base constant", then you get T(n) = nc + c0, which means the work done is in O(n).
The binary search example is similar, but you've got to make a substitution - try letting n = 2^m, and see where you can get with it. Finally, deriving the big O notation of eg. T(n) = T(sqrt(n)) + c is a really cool exercise.
Edit: There are other ways to solve recurrence relations - the Master Theorem is a standard method. But the proof isn't particularly nice and the above method works for every recurrence I've ever applied it to. And... well, it's just more fun than plugging values into a formula.
In your case recurrence relation is:
T(n) = T(n-1) + constant
And Master theorem says:
T(n) = aT(n/b) + f(n) where a >= 1 and b > 1
Here Master theorem can not be applied because for master theorem
b should be greater than 1 (b>1)
And in your case b=1
This question already has answers here:
What is a plain English explanation of "Big O" notation?
(43 answers)
Closed 5 years ago.
I have a pseudo code from university:
(0) initialize logic array prim[ n ]
(1) prim[ 1 ] = false
(2) for i = 2 to n do
(3) for k = 2 to i − 1 do
(4) if i % k == 0 then
(5) break
(6) prim[i] = (k == i) // Was loop (3) fully executed?
(7) return prim[]
Now I have to calculate the Big O for this pseudo code.
We learnt to make it step by step, by adding up the number of operations.
This is what I got so far:
Comparisons:
(4): (n-1)(n-2) outer loop * inner loop
(6): (n-1) outer loop
(4) + (6): n^2 - 2 n + 1 operations for all comparisons
Assignments:
(1): 1
(6): (n - 1)
(1) + (6): n operations for all assignments
Division:
(4): (n-1)(n-2) outer loop * inner loop
n^2 - 3 n + 2 operations for the division.
So if you add up those numbers:
(n^2 - 2 n + 1) + n + n^2 - 3 n + 2 = 2n^2 - 4 n + 3
I think there is somewhere a misconception from my side, because the Big O should be O(n^2) but here it is O(2n^2) from what I understand.
Can you guys please help me figuring out, what my misconception is. Thanks
Your misconception is thinking that 2n^2 is not O(n^2). Big-O ignores scaling constants, so you can ignore the 2 out front.
Calculation of the inner loop is wrong:
When the outer loop (i) goes from 2 to n then the innerloop wil iterate no more then 0 + 1 + 2 + ... + n-2 times, which equals to the sum of the first n-2 natural numbers.
The formula for the sum of the first n natural numbers is n*(n+1)/2.
Since there is a -2 offset the maximum number of iterations of the innerloop would be (n-2) * (n-1) / 2.
Actually you've already got the correct answer!
Thats because O(2*n²) equals O(n²). Constants multiplicators don't affect Big-O. For more information on the math behind it I recommend reading about Asymptotic Analisys. To keep it simple, it has to do with when the n tends to infinity.
So, I was asked this question in an interview. Given a group of numbers (not necessarily distinct), I have to find the multiplication of GCD's of all possible subsets of the given group of numbers.
My approach which I told the interviewer:
1. Recursively generate all possible subsets of the given set.
2a. For a particular subset of the given set:
2b. Find GCD of that subset using the Euclid's Algorithm.
3. Multiply it in the answer being obtained.
Assume GCD of an empty set to be 1.
However, there will be 2^n subsets and this won't work optimally if the n is large. How can I optimise it?
Assume that each array element is an integer in the range 1..U for some U.
Let f(x) be the number of subsets with GCD(x). The solution to the problem is then the sum of d^f(d) for all distinct factors 1 <= d <= U.
Let g(x) be the number of array elements divisible by x.
We have
f(x) = 2^g(x) - SUM(x | y, f(y))
We can compute g(x) in O(n * sqrt(U)) by enumerating all divisors of every array element. f(x) can be computed in O(U log U) from high to low values, by enumerating every multiple of x in the straightforward manner.
Pre - Requisite :
Fermat's little theorem (there is a generalised theorem too) , simple maths , Modular exponentiation
Explanation : Notations : A[] stands for our input array
Clearly the constraints 1<=N<=10^5 , tell me that either you need a O(N * LOG N ) solution , dont try to think DP as its complexity according to me will be N * max(A[i]) i.e. approx. 10^5 * 10 ^ 6 . Why? because you need the GCD of the subsets to make a transition.
Ok , moving on
We can think of clubbing the subsets with the same GCD so as to make the complexity.
So , lets decrement an iterator i from 10^6 to 1 trying to make the set with GCD i !
Now to make the subset with GCD(i) I can club it with any i*j where j is a non negative Integer. Why ?
GCD(i , i*j ) = i
Now ,
We can build a frequency table for any element as the number is quite reachable!
Now , during the contest what I did was , keep the number of subsets with gcd(i) at f2[i]
hence what we do is sum frequency of all elements from j*i where j varies from 1 to floor(i/j)
now the subsets with a common divisor(and not GCD) as i is (2^sum - 1) .
Now we have to subtract from this sum the subsets with GCD greater than i and having i as a common divisor of gcd as i.
This can also be done within the same loop by taking summation of f2[i*j] where j varies from 1 to floor(i/j)
Now the subsets with GCD i equal to 2^sum -1 - summation of f2[ij] Just multiply i ( No . of subsets with GCD i times ) i.e. power ( i , 2^sum -1 - summation of f2[ij] ) . But now to calculate this the exponent part can overflow but you can take its % with given MOD-1 as MOD was prime! (Fermat little theorem) using modular exponentiation
Here is a snippet of my code as I am unsure that can we post the code now!
for(i=max_ele; i >= 1;--i)
{
to_add=F[i];
to_subtract = 0 ;
for(j=2 ;j*i <= max_ele;++j)
{
to_add+=F[j*i];
to_subtract+=F2[j*i];
to_subtract>=(MOD-1)?(to_subtract%=(MOD-1)):0;
}
subsets = (((power(2 , to_add , MOD-1) ) - 1) - to_subtract)%(MOD-1) ;
if(subsets<0)
subsets = (subsets%(MOD-1) +MOD-1)%(MOD-1);
ans = ans * power(i , subsets , MOD);
F2[i]= subsets;
ans %=MOD;
}
I feel like I had complicated the things by using F2, I feel like we can do it without F2 by not taking j = 1. but it's okay I haven't thought about it and this is how I managed to get AC .
Consider the following code snippet:
int fib(int N)
{
if(N<2) return 1;
return (fib(N-1) + fib(N-2));
}
Given that fib is called from main with N as 10,35,67,... (say), how many total calls
are made to fib?
Is there any relation for this problem?
PS: This is a theoretical question and not supposed to be executed.
EDIT:
I am aware of other methods for the faster computation of Fibonacci series.
I want a solution for computing number of times fib is invoked for fib(40),fib(50) ,.. without the aid of compiler and in exam condition where you are supposed to answer 40 question similar to this one in a stipulated of time ( about 30 mints).
Thanks,
Let f(n) be the number of calls made to calculate fib(n).
If n < 2 then f(n) = 1.
Otherwise, f(n) = 1 + f(n - 1) + f(n - 2).
So, f is at least O(fib(n)). In fact, f(n) is 2 * fib(n) - 1. We show this by induction:
Base cases (n < 2, that is, n = 0 or n = 1):
f(n) = 1 = 2 * 1 - 1 = 2 * fib(n) - 1.
Induction step (n >= 2):
f(n + 1) = f(n) + f(n - 1) + 1
f(n + 1) = 2 * fib(n) - 1 + 2 * fib(n - 1) - 1 + 1
f(n + 1) = 2 * fib(n + 1) - 1
There exist efficient ways to calculate any Fibonacci term. Thus the same holds for f(n).
Is there any relation for this problem
?
There is a close-form equation for the nth fibonacci number: http://en.wikipedia.org/wiki/Fibonacci_number#Closed_form_expression
In the pseudocode you posted, the number of calls satisfies the recurrence relation
x(n) = x(n-1) + x(n-2) +1 # for n>=2
x(1) = 1
x(0) = 1
This is almost same as the Fibonacci recurrence relation. Proof by induction can show that the number of calls to fib made by fib(n) is equal to 2*fib(n)-1, for n>=0.
Of course, the calculation can be sped up by using the closed form expression, or by adding code to memorize previously computed values.
As mentioned above, you need to solve the following recurring equation:
K(n)=K(n-1)+K(n-2)+1
Let's write it for n-1: K(n-1)=K(n-2)+K(n-3)+1
Now, subtract the second one from the first one:
K(n)-K(n-1) = K(n-1) - K(n-3),
or
K(n) - 2*K(n-1) + K(n-3) = 0.
The respective characteristic equation will be:
x^3 - 2*x^2 + 1 = 0.
It has the following roots: 1, (1+sqrt(5))/2, (1-sqrt(5))/2
Thus for any real A,B,C the following function
K(n) = A*(1)^n + B*((1+sqrt(5))/2)^n + C*((1-sqrt(5))/2)^n
will be a solution for your equation.
To find A,B,C you need to define several initial values K(0), K(1), K(2) and solve the system of equations.
phi is a constant
position = ceil(log((n - 0.5)*sqrt(5))/log(phi));
n is the fibonacci number...
position will give you the which fibonacci number is n
for example given 13 , position will be 7 - 0 1 1 2 3 5 8 13
using this position just calculate the fibonacci number at position-1 or any position you want relative to given fibonacci number.
Previous Fibo Num = floor((pow(phi,position-1)/sqrt(5))+0.5);
floor((pow(phi, position)/sqrt(5))+0.5) - is the standard formula for calculating Nth fibonacci num (Note - This is not an approximation)
I have just reverse this formula to calculate the position and use the position - 1 to calculate the previous fibonacci number.
Ref - http://itpian.com/Coding/20951-Given-the-Nth-fib-no-and-find-the--N-1-th-fib-number-without-calculating-from-the-beginning---------.aspx
This is a classic problem for solving with Recurrence Relations.
Specifically, the fibonacci problem has the following parameters:
f(0) = 1
f(1) = 1
f(n) = f(n-1) + f(n-2)
Once you master solving recurrences, you'll have no problem reaching the solution (which, incidently, is exactly the same as fib(n)).
Interesting question, I can't give you a formula, but I wrote a Ruby program to do it, it works on numbers I figured out on paper, and it should work for any.
#!/usr/bin/ruby
#find out how many times fib() would need to be called
def howmany(n)
a = [ ]
a.push n-1
a.push n-2
while a.select{|n| n > 2}.length > 0
a.map! do |n|
n > 2 ? [n-1,n-2] : n
end
a.flatten!
end
a.length
end
.
>> howmany(10)
=> 55
It's slow.. I'm figuring out 35 right now, I'll edit when it finishes.
Edit:
>> howmany(35)
=> 9227465