hdu3117 斐波那契前后4位

题意:
      求斐波那契的前后4位,n <= 10^8.
思路:
      至于前四位,和hdu1568的求法一样:
      http://blog.csdn.net/u013761036/article/details/38726907
后四位也很好求,后四位我们可以用矩阵+快速幂去求,斐波那契的矩阵
很好推
x0 x1 *  0 1  =  x1 x2 
         1 1

这样就直接ok了,后四位直接在跑矩阵的时候对10000取余就行了。 

#include<stdio.h>
#include<string.h>
#include<math.h>

typedef struct
{
   __int64 mat[3][3];
}A;

A mat_mat(A a ,A b)
{
  A c;
  memset(c.mat ,0 ,sizeof(c.mat)); 
  for(int k = 1 ;k <= 2 ;k ++)
  for(int i = 1 ;i <= 2 ;i ++)
  if(a.mat[i][k])
  for(int j = 1 ;j <= 2 ;j ++)
  {
     c.mat[i][j] += (a.mat[i][k]) * (b.mat[k][j]);
     c.mat[i][j] %= 10000;
  }
  return c;
}

A quick_mat(A a ,int b)
{
  A c;
  memset(c.mat ,0 ,sizeof(c.mat));
  for(int i = 1 ;i <= 2 ;i ++)
  c.mat[i][i] = 1;
  while(b)
  {
     if(b&1) c = mat_mat(c ,a);
     a = mat_mat(a ,a);
     b >>= 1;
  }
  return c;
}

int num[40];

void ini()
{
    num[0] = 0 ,num[1] = 1;
    for(int i = 2 ;i<= 39 ;i ++)
    num[i] = num[i-1] + num[i-2];
}

int main ()
{
    ini();
    int n;
    A aa;
    while(~scanf("%d" ,&n))
    {
       if(n <= 39)
       {
          printf("%d
" ,num[n]);
          continue;
       }
       double now = -0.5 * log10(5.0) + n * 1.0 * log10((1+sqrt(5.0))/2);
       double bit = now - int(now);
       int a = int(pow(10.0 ,bit) * 1000);
       aa.mat[1][1] = 0;
       aa.mat[2][1] = aa.mat[1][2] = aa.mat[2][2] = 1;
       aa = quick_mat(aa ,n);
       int b = 0 * aa.mat[1][1] + 1 * aa.mat[2][1];
       printf("%d...%04d
" ,a ,b);
    }
    return 0;
}
   

原文地址:https://www.cnblogs.com/csnd/p/12062851.html