-1

Possible Duplicate:
I want to generate the nth term of the sequence 1,3,8,22,60 ,164 in Order(1) or order of (nlogn)
Calculate the nth term of the sequence 1,3,8,22,60,164,448,1224…?

I have a recurrence relation f(n) = 2 * (f(n-1) + f(n-2)). I have to solve for f(k) mod 1000000007 where k is the input. The range of k is 1 <= k <= 1000000000?. I have tried implementing it through simple recursive function, but apparently it causes overflow for large k and hence I encounter a runtime error. I am new to algorithms and stuff, so need to know whether there exists concrete and efficient ways to solve such problems?

#include<stdio.h>
#define M 1000000007
long long unsigned res(long long unsigned n){
  if(n==1)
    return 1;
  else {
    if(n==2)
      return 3;
    else return (2*(res(n-1)%M+res(n-2)%M));
  }
}
int main(){
  int test;
  scanf("%d",&test);
  while(test--){
    long long unsigned n;
    scanf("%llu",&n);
    printf("%llu\n",res(n));
  }
  getch();
  return 0;
} 
Community
  • 1
  • 1
jigsawmnc
  • 444
  • 5
  • 15

2 Answers2

0

You can use the two following identities:

mod(a * b, p) = mod(mod(a, p) * mod(b, p), p)
mod(a + b, p) = mod(mod(a, p) + mod(b, p), p)

That gives you, assuming that mod(2, p) = 2:

mod(f(n), p) = mod(2 * mod(mod(f(n - 1), p) + mod(f(n - 2), p), p), p)

or simpler:

mod(f(n), p) = mod(mod(2 * f(n - 1), p) + mod(2 * f(n - 2), p), p)

From there it should be easy to compute f(k). And there is no need for recursion, you can do a linear resolution (this is just a variation on the fibonacci sequence).

Hint: try to keep both f(n - 1) and f(n - 2) in locals, compute f(n) from that, then update your locals and iterate.

Sylvain Defresne
  • 42,429
  • 12
  • 75
  • 85
0

First of all you have to define what happen for f(0) and f(1), because at some point you will reach them. Then you can solve it moving forward instead of backward. Start from the 2 and move forward until you reach k in that way:

f(k) {
    a = F0; // F0 is the predefined value f(0)
    b = F1; // F1 is the predefined value f(1)
    if ( k == 0 ) {
       return a;
    }
    else if ( k == 1 ) {
       returb b;
    }
    else {
       n = 2;
       while ( n < k ) {
          c=2*(a+b);
          a=b;
          b=c;
          n = n+1;
       }
       return c;
    }
}

If you call it many times, you should consider save all the c somewhere, so you don't have to recalculate it every time. I hope I was clear enough. Otherwise ask me again

Andrea Carron
  • 1,001
  • 13
  • 22