题意:求斐波那契数,如果位数不超过8位就直接输出。
如果超过8位,就输出前四位+“...”+后四位。
分析:
打表发现前40项不超过8位。所以前40个直接输出。
最后超过8位的斐波那契数。
对于后4位用快速矩阵幂求出。
对于前4位,利用公式求出。
由f[n] = 1/sqrt(5)*(((1+sqrt(5))/2)^n-((1-sqrt(5))/2)^n)可知,
当n比较大时,(1-sqrt(5))/2)^n会变得很小,以至于它不会出现在前4位。
所以我们只需要计算1/sqrt(5)*( (1+sqrt(5))/2)^n ).假设等于t*10^k
利用对数进行求。即是先进行对数,
变成log10( 1/sqrt(5) )+n*log( ( 1+sqrt(5) )/2 ) .取掉整数,
也就是求留下,因为log10(t)<1,然后将其复原,即是pow(10.0,t)。
如果超过8位,就输出前四位+“...”+后四位。
分析:
打表发现前40项不超过8位。所以前40个直接输出。
最后超过8位的斐波那契数。
对于后4位用快速矩阵幂求出。
对于前4位,利用公式求出。
由f[n] = 1/sqrt(5)*(((1+sqrt(5))/2)^n-((1-sqrt(5))/2)^n)可知,
当n比较大时,(1-sqrt(5))/2)^n会变得很小,以至于它不会出现在前4位。
所以我们只需要计算1/sqrt(5)*( (1+sqrt(5))/2)^n ).假设等于t*10^k
利用对数进行求。即是先进行对数,
变成log10( 1/sqrt(5) )+n*log( ( 1+sqrt(5) )/2 ) .取掉整数,
也就是求留下,因为log10(t)<1,然后将其复原,即是pow(10.0,t)。
然后不断乘上10,直到大于等于1000,就是前4位了。
/*//
HDU 3117 快速矩阵幂
//*/
#include <cstdio>
#include <cstring>
#include <cmath>
int n,mod=10000;
const double fib=(1+sqrt(5.0))/2.0;
struct Matrix
{
int m[2][2];
void clear()
{
memset(m,0,sizeof(m));
}
}E, Z;
Matrix Mut(Matrix A, Matrix B)
{
Matrix ans;
for (int i = 0; i<2; i++)
for (int j = 0; j<2; j++)
{
ans.m[i][j] = 0;
for (int k = 0; k<2; k++)
{
ans.m[i][j] += ((A.m[i][k])*(B.m[k][j]));
ans.m[i][j]%=mod;
}
}
return ans;
}
Matrix Pow(Matrix A, int b)
{
Matrix t = A, ans = E;
while (b)
{
if (b % 2)
ans = Mut(ans, t);
b /= 2;
t = Mut(t, t);
}
return ans;
}
int front4(int n)
{
//log10(1/sqrt(5.0))=log10(1)-log(sqrt(5.0))
//=0 - 0.5 * log (5.0)
double k=-0.5*( log10(5.0) )+n*log10(fib);
k=k-(int)k;
k=pow(10.0,k);
while(k<1000)
k*=10;
return (int)k;
}
int main()
{
// freopen("in.txt", "r", stdin);
Matrix A;
int f[50];
f[0]=0;f[1]=1;
for(int i=2;i<40;i++) //打表列出前40项
{
f[i]=f[i-1]+f[i-2];
}
while(scanf("%d",&n)!=EOF)
{
if(n<40)
{
printf("%d\n",f[n]);
continue;
}
//初始化A
A.clear();
A.m[0][0]=1;A.m[0][1]=1;
A.m[1][0]=1;A.m[1][1]=0;
E=A;
//后4位。
Matrix ans=Pow(E,n-2);
int f4=front4(n);
//注意格式
printf("%d...%04d\n",f4,ans.m[0][0]);
}
return 0;
}