NYOJ 875 小M的操作数

来源:互联网 发布:ip网络公共广播系统 编辑:程序博客网 时间:2024/09/21 09:25

小M的操作数

时间限制:1000 ms  |  内存限制:65535 KB
难度:2
描述
最近小M上课老瞌睡,落下许多功课,现在就遇到了一个问题:
当一个数对(x,y)中有一个数大于或等于m时(当然有两个更好了),我们称它为m数对。一个数对(x,y)可以经过一步操作变成变成(x,x+y)或(x+y,y)数对。现在计算一个数对(x,y)变成m数对最少的操作次数吗? 你能帮助小M吗,输出最小的操作次数,如果不能变成m数对输出-1。
输入
输入x,y,m,( -10^18 ≤ x , y , m ≤ 10^18 )
输出
输出结果。
样例输入
1  2  50 -1  5
样例输出
2-1


此题是给定(x,y)数对,问至少经过多少次变换能使至少有一个数大于或等于m。

假设x>0,y>0,我们每次用x+y来替换x,y中较小的那个,假设x<y,则第一次操作后变成(x+y,y),第二次操作后变成(x+y,x+2*y)

第三次后变成(2*x+3*y,x+2*y)…………第k次操作后较大的数等于fib[k]*y + fib[k-1]*x,其中fib[ ]是斐波那契数。

对于x,y小于0的,转换成正的即可。


#include<stdio.h>#include<algorithm>using namespace std;typedef long long LL;LL fib[100];void get_fib(){    fib[0] = 1; fib[1] = 1;    for(int i = 2; i <= 90; i++)        fib[i] = fib[i-1] + fib[i-2];}int main(){    get_fib();    LL x, y, m;    while(~scanf("%lld%lld%lld",&x, &y, &m))    {        LL temp, i, sum = 0;        if(x >= m || y >= m)        {            printf("0\n");            continue;        }        if(x > y) swap(x,y);        if(x <= 0 && y <= 0)        {            if(y >= m)  printf("0\n");            else  printf("-1\n");            continue;        }        if(x < 0 && y > 0)        {            sum = (-x) / y + 1;            x += sum * y;        }//求出把x变成正数需要的次数        if(x > y) swap(x,y);        for(i = 1; i <= 90; i++)        {            temp = fib[i]*y + fib[i-1]*x;            if(temp >= m)                break;        }        printf("%lld\n",sum + i);    }    return 0;}


原创粉丝点击