• 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; }



  • 相关阅读:
    《代码整洁之道》之四 注释
    《代码整洁之道》之三 函数
    《代码整洁之道》之二 有意义的命名
    《代码整洁之道》
    Hibernate学习笔记
    Struts2复习笔记
    学习Spring必学的Java基础知识
    Eclipse下搭建Maven框架
    onvif实现
    rtmp服务端实现
  • 原文地址:https://www.cnblogs.com/tinyork/p/4882114.html
Copyright © 2020-2023  润新知