Description
Input
Sample Input
0 1 2 3 4 5 35 36 37 38 39 40 64 65
Sample Output
0 1 1 2 3 5 9227465 14930352 24157817 39088169 63245986 1023...4155 1061...7723 1716...7565
对于小于等于100000000的斐波那契数我们先打个表呗,这个简单,直接输出~~
对于剩下的斐波那契数:
前4位,推导公式:
首先我们得知道斐波那的契封闭公式:
然后,求一个数的前4位数,怎么办?~~~~~~~~~~~~~~
举个例子: s=d.xxx*10^(len-4) (len为s的总位数)
得到 log10(s)=log10(d.xxx)+len-4
于是 log10(d.xxx)=log10(s)-len+4
继续推~~得到 d.xxxxxxxxxxx=10^(log10(s)-len+4);
又 s=(1/sqrt(5))*[(1+sqrt(5))/2.0]^n;(这里的s为什么和封闭公式中的不同呢?!想想((1-sqrt(5))2)^n的具体数值该有多么小吧!!是不是可以直接忽略!!!
len=(int)log10(s)+1;
这样d不是就很容易就求出来啦?!
后4位,矩阵连乘:
求矩阵之后只需找到对应的矩阵中的数字就ok啦~
只不过矩阵连乘需要用到二分,和快速幂一样~~;
下面是代码:
#include <iostream> #include<math.h> #include<stdio.h> using namespace std; int f[40]; struct data { int jz[2][2]; }; data p={0,1, 1,1}; data q={1,0, 0,1}; int jl; void get() { f[0]=0,f[1]=1;int i; for(i=2;;i++) { f[i]=f[i-1]+f[i-2]; if(f[i]>=100000000) {jl=i-1;break;} } } int hh(int n) { return pow(10,(log10(1/sqrt(5.0))+n*log10((1+sqrt(5.0))/2.0)-(int)(log10(1/sqrt(5.0))+n*log10((1+sqrt(5.0))/2.0))+3)); } data jzcf(data a,data b)//矩阵相乘 { data c; for(int i=0;i<2;i++) for(int j=0;j<2;j++) { c.jz[i][j]=0; for(int k=0;k<2;k++) c.jz[i][j]+=(a.jz[i][k]*b.jz[k][j])%10000; c.jz[i][j]%=10000; } return c; } data quickpow(long long n)//和快速幂类似的矩阵连乘 { data m = p, b = q; while (n >= 1) { if (n & 1) b = jzcf(b,m); n = n >> 1; m = jzcf(m,m); } return b; } int main() { long long n; get(); while(cin>>n) { if(n<=jl)cout<<f[n]<<endl; else { cout<<hh(n)<<"..."; data x=quickpow(n); printf("%04d\n",x.jz[0][1]); } } return 0; }