• HDU1588


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1588

    题目大意:g(i)= k * i + b. 给定 k 和 b,求0 <= i < n 的斐波那契数 F(g(i))的和模1,000,000,000.

    解题思路:

      矩阵快速幂再加上二分矩阵公式。

      首先,我们需要认识到的一点是:对于这种求斐波那契数的题,很多都是用矩阵快速幂根据如下公式来计算的。

                                             

      我们在此把中间那个01矩阵设为A。要求 The_Sum_of_F(g(i)),只需求出 A^(g(0)-1) + A^(g(1)-1) + A^(g(2)-1) + ... + A^(g(n-1)-1) = A^(b-1) + A^(i+b-1) + A^(2*i+b-1) + ...... = A^(b-1) + A^(b-1) * (A^i + A^(2*i) + A^(3*i) + ......). A^(b-1) = Ab, A^i = Ai,这些都可以用矩阵快速幂求出来。那么式子就变成:Ab+Ab * (Ai + Ai^2 + Ai^3 + ......).加粗的那部分用二分矩阵公式递归求出。下面给出二分矩阵公式的一个例子:A^1+A^2+A^3+A^4+A^5+A^6=(A^1+A^2+A^3)+A^3(A^1+A^2+A^3)。

    AC代码:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 using namespace std;
     5 typedef long long ll;
     6 const int maxn = 1000;
     7 struct Matrix {
     8     ll mat[4][4];
     9 };
    10 Matrix E;
    11 ll M;
    12 Matrix Multiply(Matrix x,Matrix y) {    
    13     Matrix temp;
    14     memset(temp.mat, 0, sizeof(temp.mat));
    15     for (int i = 0; i < 2; i++)
    16         for (int j = 0; j < 2; j++) {
    17             for (int k = 0; k < 2; k++) {
    18                 temp.mat[i][j] += (x.mat[i][k] * y.mat[k][j]%M);
    19                 temp.mat[i][j]%=M;
    20             }
    21         }
    22     return temp;
    23 }
    24 Matrix Add(Matrix x,Matrix y){
    25     Matrix temp;
    26     for (int i = 0; i < 2; i++){
    27         for (int j = 0; j < 2; j++) {
    28             temp.mat[i][j]=(x.mat[i][j]+y.mat[i][j])%M;
    29         }
    30     }
    31     return temp;
    32 }
    33 Matrix Fast_Power(Matrix a, int m) {        //求a的m次幂
    34     Matrix res;
    35     memset(res.mat, 0, sizeof(res.mat));
    36     for (int i = 0; i < 2; i++)        res.mat[i][i] = 1;
    37     while (m) {
    38         if (m & 1)    res = Multiply(res, a);
    39         m >>= 1;
    40         a = Multiply(a, a);
    41     }
    42     return res;
    43 }
    44 Matrix Binary_add(Matrix B,int t){
    45     if(t==1)    return B;
    46     if(t%2==1){
    47         return Add(Multiply(Binary_add(B,(t-1)/2),Add(E,Fast_Power(B,(t-1)/2))),Fast_Power(B,t));
    48     }
    49     else
    50         return Multiply(Binary_add(B,t/2),Add(E,Fast_Power(B,t/2)));
    51 }
    52 int main()
    53 {
    54     E.mat[0][0]=E.mat[1][1]=1;
    55     E.mat[0][1]=E.mat[1][0]=0;
    56     Matrix A;
    57     A.mat[0][0]=A.mat[0][1]=A.mat[1][0]=1;
    58     A.mat[1][1]=0;
    59     ll k,b,n,t;
    60     while(scanf("%lld%lld%lld%lld",&k,&b,&n,&M)==4){
    61         Matrix Ab,B,ans;
    62         B=Fast_Power(A,k);
    63         Ab=Fast_Power(A,b);
    64         ans=Add(Ab,Multiply(Ab,Binary_add(B,n-1)));
    65         printf("%lld
    ",ans.mat[1][0]);
    66     }
    67     return 0;
    68 }
    “这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”
  • 相关阅读:
    pat00-自测5. Shuffling Machine (20)
    Spiral Matrix
    Search in Rotated Sorted Array II
    Search in Rotated Sorted Array
    Best Time to Buy and Sell Stock II
    4Sum
    3Sum Closest
    3Sum
    MySQL存储过程、函数和游标
    Word Ladder
  • 原文地址:https://www.cnblogs.com/Blogggggg/p/7367657.html
Copyright © 2020-2023  润新知