ural 1133 Fibonacci Sequence 二分枚举

给出Fibonacci的第i项和第j项。求第n项。

Input

The input contains five integers in the following order: iFij,Fjn.
−1000 ≤ ijn ≤ 1000, i ≠ j,
−2·109 ≤ Fk ≤ 2·109 (k = min(ijn), …, max(ijn)).

Output

The output consists of a single integer, which is the value of Fn.

Sample

Input : 3 5 -1 4 5
Ouput : 12

答案计算:
f[3]=f[2]+f[1]=2f[1]+f[0]=3f[0]+f[-1],
即5=3f[0]+4, 得f[0]=-1
f[5]=f[4]+f[3]=2f[3]+f[2]=10+f[1]+f[0]=10+2f[0]+f[-1]=10-2+4=12

1)求f[i+1]
斐波那契数列是相邻两项的关系,ij不相邻,要先求出i+1项。
1)方程计算
列出fi,fj,f(i+1)的关系 : fj = a[j-i-1]f[i+1] + a[j-i-2]f[i]
其中,a数列满足a[i]=a[i-1]+a[i-2],也是一个斐波那契数列,这里j-i>0,且i j已知,所以可以求得。
这种方法求出a[i+1]复杂度应该是2000以内的,不知道为什么超时了。
2)二分求解
f的范围是[-2*10^9, 2*10^9] ,而斐波那契数列是单调的,从最大最小数开始枚举,从f[i]和f[i+1]递推求j项,和f[j]对比,调整枚举空间。二分是log(10^9)很快。像平时玩猜数字游戏一样。10^9里找一个数字一会儿就找出来了。
2)求f[n]

  从f[i]和f[i+1]递推求

二分代码:
const long long MAXN = 2000000000;
long long i,fi,j,fj,n;
void swap(long long &i,long long &j) { i=i+j; j=i-j; i=i-j; }

int main()
{  
    cin >> i >> fi >> j >> fj >> n;
    if(i>j) {swap(i,j);swap(fi,fj);}
    // cal f[i+1]
    long long l=-MAXN, r=MAXN, mid;
    long long ti=fi, tj=mid, t;
    while (l+1<r){
        mid = (l+r)/2;
        ti=fi; tj=mid;
        for (int k=i+2; k<=j; ++k){
            t=ti+tj; 
       ti=tj;
       tj=t; if(t>MAXN*2 ||t<-MAXN*2) break; } if(tj>=fj) r = mid;   else l=mid; } ti=fi; tj=r; if(n>i){ for(int k=i+2;k<=n;++k){ t=ti+tj;
       ti=tj;
       tj=t; } cout << tj << endl; } else { for(int k=i-1; k>=n; ++k){ t=tj-ti;
       tj=ti;
       ti=t; } cout << ti << endl; } cin >> ti; return 0; }

 




posted @ 2015-10-15 13:04  y丫t  阅读(184)  评论(0编辑  收藏  举报