0 1 2 3 4 5 35 36 37 38 39 40 64 65
0 1 1 2 3 5 9227465 14930352 24157817 39088169 63245986 1023...4155 1061...7723 1716...7565
题解及代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define s_5 sqrt(5.0)
#define sl_5 (0.5+sqrt(5.0)/2.0)
#define sr_5 (0.5-sqrt(5.0)/2.0)
using namespace std;
int fibo[50];
void init()
{
fibo[0]=0;
fibo[1]=1;
int i;
for(i=2;i<=50;i++)
{
fibo[i]=fibo[i-1]+fibo[i-2];
if(fibo[i]>=100000000)
{
break;
}
}
}
struct mat
{
long long t[2][2];
void set()
{
memset(t,0,sizeof(t));
}
}a,b;
mat multiple(mat a,mat b,int n,int p)
{
int i,j,k;
mat temp;
temp.set();
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
if(a.t[i][j])
for(k=0;k<n;k++)
temp.t[i][k]=(temp.t[i][k]+a.t[i][j]*b.t[j][k])%p;
}
return temp;
}
mat quick_mod(mat b,int n,int p)
{
mat t;
t.t[0][0]=1;
t.t[0][1]=0;
t.t[1][0]=0;
t.t[1][1]=1;
while(n)
{
if(n&1)
{
t=multiple(t,b,2,p);
}
n>>=1;
b=multiple(b,b,2,p);
}
return t;
}
void init1()
{
b.t[0][0]=1;
b.t[0][1]=1;
b.t[1][0]=1;
b.t[1][1]=0;
}
int main()
{
int n;
init();
while(cin>>n)
{
if(n<40)
{
cout<<fibo[n]<<endl;
continue;
}
double s=log10(1.0/s_5)+n*log10(sl_5);
int len=(int)s+1;
double t=s-len+4;
cout<<(int)pow(10.0,t);
init1();
a=quick_mod(b,n,10000);
printf("...%04d\n",a.t[1][0]);
}
return 0;
}
/*
一道比较简单的数学题,输出斐波那契数的前四位和后四位。
对于前40项,直接打表输出就可以了。
接下来我们讲一下大于40位的时候如何计算:
对于后四位,我们可以想到,我们进行滚动数组取余就能求得答案,
但是数据量有点大,这样可定会超时,所以只能使用矩阵快速幂来加速。
对于前四位,我们要使用到斐波那契数的封闭公式:
f[n]=1/sqrt(5)*{[0.5+sqrt(5)/2]^n-[0.5-sqrt(5)/2]^n};
由于n很大时,[0.5-sqrt(5)/2]^n很小,几乎可以忽略,又因为我们计算
的是前四位,所以不必管后面的精度,所以这一项可以省略。
f[n]=1/sqrt(5)*[0.5+sqrt(5)/2]^n;
我们假定t=f[n],k为其前四位,想要求t的前四位数k,我们可以使用科学
计数法来写一下t,t=k.xxxx……*10^(len-4);这里len指的是t的位数。
而计算一个数的位数可以使用log10(t)+1来计算得到。
那么知道了这些就很好计算了:首先我们先求出t的位数
len=log10(1/sqrt(5)*[0.5+sqrt(5)/2]^n);
化简一下:len=log10(1/sqrt(5))+n*log10(0.5+sqrt(5)/2);
对于t=k.xxxx……*10^(len-4);我们两边进行log10取对数,
得到log10(t)=log10(k.xxxx……)+len-4;
化简一下得到log10(k.xxxx……)=log10(t)-(len-4);
那么我们为了得到k.xxx……,我们可以求10^[log10(t)-(len-4)]就行了,
最后一项,对k取整。
*转载请注明出处,谢谢。
*/
hdu 3117 Fibonacci Numbers,布布扣,bubuko.com
原文:http://blog.csdn.net/knight_kaka/article/details/38304861