小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 5 0 -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; }