hdu 3117 Fibonacci Numbers


Fibonacci Numbers

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 993    Accepted Submission(s): 424


Problem Description
The Fibonacci sequence is the sequence of numbers such that every element is equal to the sum of the two previous elements, except for the first two elements f0 and f1 which are respectively zero and one.

What is the numerical value of the nth Fibonacci number?

Input
For each test case, a line will contain an integer i between 0 and 108 inclusively, for which you must compute the ith Fibonacci number fi. Fibonacci numbers get large pretty quickly, so whenever the answer has more than 8 digits, output only the first and last 4 digits of the answer, separating the two parts with an ellipsis (“...”).

There is no special way to denote the end of the of the input, simply stop when the standard input terminates (after the EOF).

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

Source

Recommend
lcy
 
 
 
解题报告:下面举例来说明计算前4 位
123456.32=1234.56*10^2
s=d.xxx*10^(len-4)
log10(s)=log10(d.xxxxx)+log10(10^(len-4))=log10(d.xxxx)+len-4;
log10(s)+4-len=log10(d.xxxx)
d.xxxx=10^(log10(s)+4-len)
s=(1/sqrt(5))*[(1+sqrt(5))/2.0]^i;
len=(int)log10(s)+1;
d.xxxx=10^(log10(s)+4-((int)log10(s)+1))=10^(log10(s)-(int)log10(s)+3);
-----------------------------------------------------------------------------
计算后4 位 矩阵乘法幂取模,注意后4 位时 ,例如 0123 输出要占4 位,而不是123
-------------------------------------------------------------------------
先把前8 位的fibonacci 的值打表打出来;8 位以后的f(i)的值用上面方法
后四位:用矩阵连乘
在矩阵连乘的时候边乘边取余;
/*===================================*/
|| 快速幂(quickpow)模板
|| P 为等比,I 为单位矩阵
|| MAX 要初始化!!!!
||
/*===================================*/
/*****************************************************/
#include <cstdio>
const int MAX = 3;
typedef struct{
int m[MAX][MAX];
} Matrix;
Matrix P = {5,-7,4,
1,0,0,
0,1,0,
};
Matrix I = {1,0,0,
0,1,0,
0,0,1,
};
Matrix matrixmul(Matrix a,Matrix b) //矩阵乘法
{
int i,j,k;
Matrix c;
for (i = 0 ; i < MAX; i++)
for (j = 0; j < MAX;j++)
{
c.m[i][j] = 0;
for (k = 0; k < MAX; k++)
c.m[i][j] += (a.m[i][k] * b.m[k][j])%9997;
c.m[i][j] %= 9997;
}
return c;
}
Matrix quickpow(long long n)
{
Matrix m = P, b = I;
while (n >= 1)
{
if (n & 1)
b = matrixmul(b,m);
n = n >> 1;
m = matrixmul(m,m);
}
return b;
}
模板解题源于陈宇老师的PDF fibonacci讲义
解题失误:1:在写矩阵连乘时,用到DP的时候,忘记了个"+",调试了会。
                  2:在提交的时候CE了几次,原来在调用SQRT()和POW()出了问题,
                    pow( 10.0, ((sqrt(5.0)+1.0)/2)),这个式子有.0的地方若少了绝对CE。            
认真真的很重要
 
 
 
 
#include<cstdio>
#include<cmath>
#define MAX 2
#define AK ((sqrt(5.0)+1.0)/2)
struct A
{
  int m[MAX][MAX];
};
 const A I={1,0,
            0,1};
const A P={1,1,1,0};
A chen(A a,A b)
{
  A c;
  for(int i=0;i<MAX;i++)
  for(int j=0;j<MAX;j++)
  {
    c.m[i][j]=0;
    for(int k=0;k<MAX;k++)
    {
      c.m[i][j]+=(a.m[i][k]*b.m[k][j])%10000;
    }
    c.m[i][j]%=10000;
  }
  return c;
}
A quick_pow(int k)
{
  A b,m;
  b=I;m=P;
  while(k>0)
  {
    if(k&1)
   {
    b=chen(b,m);
   }
   k>>=1;
    m=chen(m,m);
  }
  return b;
}
int main()
{
  long long f[50];
f[0]=0;
f[1]=1;
for(int j=2;j<41;j++)
{
  f[j]=f[j-1]+f[j-2];
}
  int m;
  double former;
  int last;
  while(scanf("%d",&m)!=EOF)
  {
    if(m<40)
    {
      printf("%lld\n",f[m]);
      continue;
    }
    A k=quick_pow(m);
    last=k.m[0][0]*f[0]+k.m[0][1]*f[1];
    last%=10000;
    former=-0.5*log10(5.0)+m*log10(AK);
    former=former-(int)former+3;
    former=pow(10.0,former);
    printf("%d...%004d\n",(int)former,last);
  }
}

 
posted @ 2012-07-21 12:04  剑不飞  阅读(307)  评论(0编辑  收藏  举报