题目链接:点击打开链接
// csu 1941
// 大概题意:求一个a* f[i]+b* f[i- 1]= g的解,b为第一关键字最小,a为第二关键字
#include <iostream>
#include <algorithm>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
#define ll long long
using namespace std;
ll f[50];
ll gcd(ll a, ll b)
{
if(!b) return a; else return gcd(b, a% b);
}
void exgcd(ll a, ll b, ll &d, ll &x, ll &y)
{
if(!b) { d= a; x= 1; y= 0; }
else { exgcd(b, a% b, d, y, x); y-= x* (a/ b); }
}
int main()
{
f[1]= 1; f[2]= 1;
for(int i= 3; i<= 50; i++) f[i]= f[i- 1]+ f[i- 2];
int T; cin >> T;
while(T--)
{
ll g, ansa= 1000000007, ansb= 1000000007, anst; scanf("%lld", &g);
for(int i= 1; i<= 50; i++)
if(g% gcd(f[i], f[i+ 1])== 0) // 其实由于斐波那契相邻两项互质(没有证明)可以省去这一步,并且之后的d都省略
{
ll x, y, d, a= f[i], b= f[i+ 1];
exgcd(a, b, d, x, y);
x*= g/ d; y*= g/ d; //调用后,(x,y)为最靠近零的整数解
if(x<= 0)
{
ll k= b/ d;
ll xx= (x% k+ k)% k;
ll t= (xx- x)/ k;
x= xx; y-= t* a/ d;
}
/*
ll t= abs(y- x)/(a/ d+ b/ d);
if(x< y) { x+= b* t/ d; y-= a* t/ d; } //这几行很丑!完全抄的非正解
else // y= y0- a/ d* t x= x0+ b/ d* t;
{ // y> x 然后推出t的范围.......至于这样做为什么对完全不解;
if(abs(y- x)% (a/ d+ b/ d)) t++; //应该是因为exgcd本身的性质吧!不过好像懂一点点了,
x-= b* t/ d; y+= a* t/ d;
}
*/
ll t= (y- x)/(a/ d+ b/ d); //这是我自己改的,貌似科学了点,但是还是wa
ll x0= x, y0= y; //就是说abs(y0- x0)% (a/ d+ b/ d)不是整除的时候,c++是向0取整,当t为负时所以这时要t--
x=x0+ b* t/ d; y=y0- a* t/ d; //貌似对了!嘎嘎嘎嘎嘎嘎!!!!!
if((y0< x0) && abs(y0- x0)% (a/ d+ b/ d)) { t--; x=x0+ b* t/ d; y=y0- a* t/ d;}
if((x> 0) && (y>= x) && ((y< ansb) || (y== ansb && x< ansa)))
{
ansb= y; ansa= x; anst= a* t;
}
}
printf("%lld %lld\n", ansa, ansb);
}
return 0;
}