题目大意:给定一个数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);
}
}