zoukankan      html  css  js  c++  java
  • POJ3070Fibonacci(矩阵快速幂求Fibonacci数列)

    Fibonacci
    Time Limit: 1000MS   Memory Limit: 65536K
    Total Submissions: 7241   Accepted: 5131

    Description

    In the Fibonacci integer sequence, F0 = 0, F1 = 1, and Fn = Fn − 1 + Fn − 2 for n ≥ 2. For example, the first ten terms of the Fibonacci sequence are:

    0, 1, 1, 2, 3, 5, 8, 13, 21, 34, …

    An alternative formula for the Fibonacci sequence is

    .

    Given an integer n, your goal is to compute the last 4 digits of Fn.

    Input

    The input test file will contain multiple test cases. Each test case consists of a single line containing n (where 0 ≤ n ≤ 1,000,000,000). The end-of-file is denoted by a single line containing the number −1.

    Output

    For each test case, print the last four digits of Fn. If the last four digits of Fn are all zeros, print ‘0’; otherwise, omit any leading zeros (i.e., print Fn mod 10000).

    Sample Input

    0
    9
    999999999
    1000000000
    -1

    Sample Output

    0
    34
    626
    6875

    Hint

    As a reminder, matrix multiplication is associative, and the product of two 2 × 2 matrices is given by

    .

    Also, note that raising any 2 × 2 matrix to the 0th power gives the identity matrix:

    .

    Source

     
    分析:通过这道题,不仅学会了矩阵的快速幂的做法,同时也提供了求Fibonacci的高效算法
    代码一: 
       这题完全套用的是 一般的快速幂的做法,只不过改成矩阵乘法后,为了在做矩阵乘法过程中不会影响结果值,
    之间要用中间变量,代码写的很难看 (没有想到可以用结构体对二维数组进行封装,可以直接返回结构体类型的数据),
    不过还是 0ms AC。 
     1 #include <cstdio>
     2 #include <iostream>
     3 
     4 using namespace std;
     5 
     6 const int MOD = 10000;
     7 
     8 int fast_mod(int n)    // 求 (t^n)%MOD 
     9 {
    10     int t[2][2] = {1, 1, 1, 0};
    11     int ans[2][2] = {1, 0, 0, 1};  // 初始化为单位矩阵
    12     int tmp[2][2];    //自始至终都作为矩阵乘法中的中间变量 
    13      
    14     while(n)
    15     {
    16         if(n & 1)  //实现 ans *= t; 其中要先把 ans赋值给 tmp,然后用 ans = tmp * t 
    17         {
    18             for(int i = 0; i < 2; ++i)
    19                 for(int j = 0; j < 2; ++j)
    20                     tmp[i][j] = ans[i][j]; 
    21             ans[0][0] = ans[1][1] = ans[0][1] = ans[1][0] = 0;  // 注意这里要都赋值成 0 
    22             
    23             for(int i = 0; i < 2; ++i)    //  矩阵乘法 
    24             {
    25                 for(int j = 0; j < 2; ++j)
    26                 {
    27                     for(int k = 0; k < 2; ++k)
    28                         ans[i][j] = (ans[i][j] + tmp[i][k] * t[k][j]) % MOD;
    29                 }
    30             }
    31         }
    32         
    33         //  下边要实现  t *= t 的操作,同样要先将t赋值给中间变量  tmp ,t清零,之后 t = tmp* tmp 
    34         for(int i = 0; i < 2; ++i)
    35             for(int j = 0; j < 2; ++j)
    36                 tmp[i][j] = t[i][j];
    37         t[0][0] = t[1][1] = 0;
    38         t[0][1] = t[1][0] = 0;
    39         for(int i = 0; i < 2; ++i)
    40         {
    41             for(int j = 0; j < 2; ++j)
    42             {
    43                 for(int k = 0; k < 2; ++k)
    44                     t[i][j] = (t[i][j] + tmp[i][k] * tmp[k][j]) % MOD;
    45             }
    46         }
    47         
    48         n >>= 1;
    49     }
    50     return ans[0][1];
    51 }
    52 
    53 int main()
    54 {
    55     int n;
    56     while(scanf("%d", &n) && n != -1)
    57     {    
    58         printf("%d\n", fast_mod(n));
    59     }
    60     return 0;
    61 }

    代码二:用结构体封装矩阵乘法后,代码看着清晰多了

     1 #include <cstdio>
     2 #include <iostream>
     3 
     4 using namespace std;
     5 
     6 const int MOD = 10000;
     7 
     8 struct matrix
     9 {
    10     int m[2][2];
    11 }ans, base;
    12 
    13 matrix multi(matrix a, matrix b)
    14 {
    15     matrix tmp;
    16     for(int i = 0; i < 2; ++i)
    17     {
    18         for(int j = 0; j < 2; ++j)
    19         {
    20             tmp.m[i][j] = 0;
    21             for(int k = 0; k < 2; ++k)
    22                 tmp.m[i][j] = (tmp.m[i][j] + a.m[i][k] * b.m[k][j]) % MOD;
    23         }
    24     }
    25     return tmp;
    26 }
    27 int fast_mod(int n)  // 求矩阵 base 的  n 次幂 
    28 {
    29     base.m[0][0] = base.m[0][1] = base.m[1][0] = 1;
    30     base.m[1][1] = 0;
    31     ans.m[0][0] = ans.m[1][1] = 1;  // ans 初始化为单位矩阵 
    32     ans.m[0][1] = ans.m[1][0] = 0;
    33     while(n)
    34     {
    35         if(n & 1)  //实现 ans *= t; 其中要先把 ans赋值给 tmp,然后用 ans = tmp * t 
    36         {
    37             ans = multi(ans, base);
    38         }
    39         base = multi(base, base);
    40         n >>= 1;
    41     }
    42     return ans.m[0][1];
    43 }
    44 
    45 int main()
    46 {
    47     int n;
    48     while(scanf("%d", &n) && n != -1)
    49     {   
    50         printf("%d\n", fast_mod(n));
    51     }
    52     return 0;
    53 }
  • 相关阅读:
    SQL Server 优化-执行计划
    SQL Server 开发-语法学习
    MySQL管理_数据库常用命令
    MySQL管理_数据库启动与关闭
    SQL Server DBA日常查询视图_数据库性能视图
    SQL Server DBA性能优化
    MySQL系列 | MySQL高级-08逻辑架构
    工具系列 | Docker基本概念
    PHP系列 | [转] PHP中被忽略的性能优化利器:生成器
    PHP系列 | 代码复用trait的构造函数使用
  • 原文地址:https://www.cnblogs.com/dongsheng/p/3114073.html
Copyright © 2011-2022 走看看