题目大意:给定一个数n,按斐波那契数规则生成,求最小的b,并使a最小。G1 = a , G2 = b; b >= a.
思路分析:
因为n<10^9,所以斐波那契数列的项数不可能超过46.题目转换为求ax+by=n的最小的x,y。根据欧几里得
#include <iostream> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <cstdio> using namespace std; #define maxn 99999999 #define mem(a) memset(a , 0 , sizeof(a)) #define LL __int64 LL fib[65]; void init() { fib[0] = 1; fib[1] = 1; fib[2] = 2; for(int i = 3 ; i < 65 ; i ++) { fib[i] = fib[i-1] + fib[i-2]; } return ; } void gcd2(LL a , LL b , int &d ,LL &x , LL &y) { if(!b) { d = a; x = 1 ; y = 0; } else { gcd2(b , a%b , d , y , x); y -= x*(a/b); } } int main() { int t; LL n; init(); scanf("%d" , &t); while(t-- ) { scanf("%I64d" , &n); int pos; pos = 65; LL ansx = (LL)maxn*1000, ansy = (LL)maxn*1000; LL x , y ;int d; while(pos > 2) { LL a = fib[pos - 2], b = fib[pos - 1]; pos -- ; gcd2(a , b , d , x , y); x *= n/d ; y *= n/d; LL t1 = b / d; LL t2 = a / d; x = (x % t1 + t1) % t1; //找到最小正整数x y = (n - a * x) / b; //对应的y; ////////////并没有看懂这个 ll k = (y-x-1) / (ma+mb);//优化 x += ma*k, y -= mb*k; /* int abc; if(x <= 0) { abc = abs(x / b); if(x % b != 0) abc ++; x = x + abc * b / d; y = y - abc * a / d; } if(y <= 0) { abc = abs(y / a); if(y % a != 0) abc ++; x = x - abc * b / d; y = y + abc * a / d; } if(x < 0 || y + x < 0) continue; if( x == 0) swap(x , y); else if(y != 0 && x > y) swap(x , y); if(x == 0 && y == 0) continue;*/ while(y >= x && y < ansy) { if(y < ansy || (y == ansy && x < ansx) && x > 0) ansx = x , ansy = y; x += t1 , y -= t2; } } if(ansx == 0) ansx = ansy ; printf("%I64d %I64d\n" , ansx ,ansy); } }