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 5Ouput : 12

答案计算:f[3]=f[2]+f[1]=2f[1]+f[0]=3f[0]+f[-1],即5=3f[0]+4, 得f[0]=-1f[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;
}
				
时间: 2024-11-11 16:09:49

ural 1133 Fibonacci Sequence 二分枚举的相关文章

URAL 1133 Fibonacci Sequence(数论)

题目链接 题意 :给你第 i 项的值fi,第 j 项的值是 fj 让你求第n项的值,这个数列满足斐波那契的性质,每一项的值是前两项的值得和. 思路 :知道了第 i 项第j项,而且还知道了每个数的范围,二分求第 i+1项,然后根据性质求下去,求到第 j 项的时候看看通过二分求出来的值与给定的第j项的值大小关系,来确定下一次二分的值,输出的时候注意方向. #include <stdio.h> #include <string.h> #include <iostream> #

记忆化搜索+DFS URAL 1183 Brackets Sequence

题目传送门 1 /* 2 记忆化搜索+DFS:dp[i][j] 表示第i到第j个字符,最少要加多少个括号 3 dp[x][x] = 1 一定要加一个括号:dp[x][y] = 0, x > y; 4 当s[x] 与 s[y] 匹配,则搜索 (x+1, y-1); 否则在x~y-1枚举找到相匹配的括号,更新最小值 5 */ 6 #include <cstdio> 7 #include <algorithm> 8 #include <cmath> 9 #include

【noi 2.2_7891】一元三次方程求解(二分枚举)

对于noi上的题有2中解法: 1.数据很小(N=100),可以直接打for循环枚举和判断. 2.不会“三分”,便用二分.利用“两根相差>=1”和 f(x1)*f(x2)<0,转换意思为[x,x+1]内不会包含两个根,这样枚举可以保证不漏解.因此,枚举一个个根所在的区间,再用二分枚举找出根.其中,若N=10^5,由于保留2位小数,最好精确到4位小数计算.时间复杂度 O(N)=10^5+3*log(10^4),约为10^5. 以下附上二分的代码—— 1 //20160908 Ann 2 #incl

HDU 5371 (2015多校联合训练赛第七场1003)Hotaru&#39;s problem(manacher+二分/枚举)

HDU 5371 题意: 定义一个序列为N序列:这个序列按分作三部分,第一部分与第三部分相同,第一部分与第二部分对称. 现在给你一个长为n(n<10^5)的序列,求出该序列中N序列的最大长度. 思路: 来自官方题解:修正了一些题解错别字(误 先用求回文串的Manacher算法,求出以第i个点为中心的回文串长度,记录到数组p中 要满足题目所要求的内容,需要使得两个相邻的回文串,共享中间的一部分,也就是说,左边的回文串长度的一半,要大于等于共享部分的长度,右边回文串也是一样. 因为我们已经记录下来以

HDU 5371 (2015多校联合训练赛第七场1003)Hotaru&amp;#39;s problem(manacher+二分/枚举)

pid=5371">HDU 5371 题意: 定义一个序列为N序列:这个序列按分作三部分,第一部分与第三部分同样,第一部分与第二部分对称. 如今给你一个长为n(n<10^5)的序列,求出该序列中N序列的最大长度. 思路: 来自官方题解:修正了一些题解错别字(误 先用求回文串的Manacher算法.求出以第i个点为中心的回文串长度.记录到数组p中 要满足题目所要求的内容.须要使得两个相邻的回文串,共享中间的一部分,也就是说.左边的回文串长度的一半,要大于等于共享部分的长度,右边回文串也

hdu 5248 序列变换(二分枚举)

Problem Description 给定序列A={A1,A2,...,An}, 要求改变序列A中的某些元素,形成一个严格单调的序列B(严格单调的定义为:Bi<Bi+1,1≤i<N). 我们定义从序列A到序列B变换的代价为cost(A,B)=max(|Ai−Bi|)(1≤i≤N). 请求出满足条件的最小代价. 注意,每个元素在变换前后都是整数. Input 第一行为测试的组数T(1≤T≤10). 对于每一组: 第一行为序列A的长度N(1≤N≤105),第二行包含N个数,A1,A2,...,A

SPOJ - AGGRCOW Aggressive cows(二分枚举最优解)

题意:给出n个位置,需要将m头牛放在这些位置中,使得所有相邻两头牛间的最小距离最大,求最大的最小距离: 思路:二分枚举最优解.先将所有位置排序,从最大总距离枚举到0,若满足差值大于等于枚举值的位置个数大于等于m,则当前枚举值为最优解. #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int t,n,m; int num[500100]; int a[500100];

寒假week1---二分查找(二分枚举)

寒假week1---二分查找(二分枚举)1.适用条件:要查找(枚举)的集合有序 && 查找(枚举)的"条件"具有单调性2.什么是"条件":example: 1.给定一个有序数组,从中查找数字7的下标.条件是:这个数字等于7. 2.给定一个有序数组,从中查找满足函数f(x)<99的数字的下标.条件是:f(x)<99.3.什么是"满足条件": 在上述例1中,所有等于7的数字都是满足条件的,例2中所有f(x)<99的x

SQL Server -&gt;&gt; 斐波那契数列(Fibonacci sequence)

斐波那契数列(Fibonacci sequence)的T-SQL实现 ;WITH T AS ( SELECT 1 AS NUM, CAST(1 AS BIGINT) AS curr, CAST(NULL AS BIGINT) AS prv UNION ALL SELECT curr.NUM + 1 AS NUM, CAST(CASE WHEN prv IS NULL THEN curr ELSE curr + prv END AS BIGINT) AS curr, CAST(curr AS BI