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 }
  • 相关阅读:
    1012 The Best Rank (25 分)(排序)
    1011. World Cup Betting (20)(查找元素)
    1009 Product of Polynomials (25 分)(模拟)
    1008 Elevator (20 分)(数学问题)
    1006 Sign In and Sign Out (25 分)(查找元素)
    1005 Spell It Right (20 分)(字符串处理)
    Kafka Connect 出现ERROR Failed to flush WorkerSourceTask{id=local-file-source-0}, timed out while wait
    flume、kafka、avro组成的消息系统
    Java23种设计模式总结【转载】
    Java编程 思维导图
  • 原文地址:https://www.cnblogs.com/dongsheng/p/3114073.html
Copyright © 2011-2022 走看看