70,037
社区成员
发帖
与我相关
我的任务
分享
#include <stdio.h>
#include <assert.h>
#include <gmp.h>
#include <math.h>
#define XSMALL_FIB_NUM_N (64)
mpz_t x_small_fib_num[ XSMALL_FIB_NUM_N ];
void init()
{
int i;
mpz_init_set_ui( x_small_fib_num[0] , 0 );
mpz_init_set_ui( x_small_fib_num[1] , 1 );
for( i = 2; i < XSMALL_FIB_NUM_N; ++i )
{
mpz_init(x_small_fib_num[i]);
mpz_add( x_small_fib_num[i] , x_small_fib_num[i-1] , x_small_fib_num[i-2] );
}
}
mpz_ptr get_small_fib( mpz_ptr r , mpz_srcptr x )
{
int i;
for( i = XSMALL_FIB_NUM_N - 1; i > 0 ; --i )
{
if( mpz_cmp( x , x_small_fib_num[i] ) >= 0 )
break;
}
mpz_set( r , x_small_fib_num[i] );
return r;
}
mpz_ptr get_fib( mpz_ptr r , mpz_srcptr x )
{
static const double l2 = .69314718055994529 , ls5 = .80471895621705025 , lfl = .48121182505960347;
if( mpz_cmp( x , x_small_fib_num[ XSMALL_FIB_NUM_N-1] ) <= 0 )
return get_small_fib( r , x );
else
{
double ex ;
signed long int bit2 ;
unsigned long N ;
mpz_t fN_1 ;
mpz_init( fN_1 );
ex = mpz_get_d_2exp( &bit2 , x );
N = (unsigned)( .5 + ( ls5 + bit2 * l2 + log( ex ) ) / lfl );
mpz_fib2_ui( r , fN_1 , N );
if( mpz_cmp( r , x ) > 0 )
mpz_swap( r , fN_1 );
mpz_clear( fN_1 );
return r;
}
}
int main()
{
mpz_t r , FN;
int X = -1;
init();
mpz_init( r );
mpz_init( FN );
gmp_printf( "%Zd\n" , x_small_fib_num[XSMALL_FIB_NUM_N-1] );
scanf( "%d" , &X );
while( X-- > 0 && 1 == gmp_scanf( "%Zd" , FN ) )
gmp_printf( "%Zd\n" , get_fib( r , FN ) );
mpz_clear( r );
mpz_clear( FN );
return 0;
}