Fibonacci(矩阵快速幂 - 递推式构造 + 变种)

POJ 3070 Fibonacci

题目链接:http://poj.org/problem?id=3070
在这里插入图片描述

题意:求Fn % 1000是多少?(公式题目已给出)
此题的公式就是Fn = Fn-1 + Fn-2,我们令:
   X n 1 = [ F n 1 F n 2 ] X_{n-1} = \begin{bmatrix}F_{n-1}\\ F_{n-2} \end{bmatrix}    X n = [ F n F n 1 ] X_{n} = \begin{bmatrix} F_{n}\\ F_{n-1} \end{bmatrix}
那么我们需要找到的矩阵 A 就满足:
       A X n 1 = X n A \cdot X_{n-1} = X_{n}
又因为:
     { F n = F n 1 + F n 2 F n 1 = F n 1 + 0 F n 2 \begin{cases} F_{n} = F_{n-1} + F_{n-2}\\ F_{n-1} = F_{n-1} + 0 \cdot F_{n-2} \end{cases}
所以:
     A = [ 1 , 1 0 , 0 ] A = \begin{bmatrix} 1,1\\ 0,0 \end{bmatrix}
即:
     [ 1 , 1 0 , 0 ] \begin{bmatrix} 1,1\\ 0,0 \end{bmatrix} \cdot [ F n 1 F n 2 ] \begin{bmatrix}F_{n-1}\\ F_{n-2} \end{bmatrix} = [ F n F n 1 ] = \begin{bmatrix} F_{n}\\ F_{n-1} \end{bmatrix}
综上所述:
     [ F n F n 1 ] = [ 1 , 1 0 , 0 ] [ F n 1 F n 2 ] = [ 1 , 1 0 , 0 ] 2 [ F n 2 F n 3 ] = [ 1 , 1 0 , 0 ] n 1 [ F 1 F 0 ] \begin{bmatrix} F_{n}\\ F_{n-1} \end{bmatrix} = \begin{bmatrix} 1,1\\ 0,0 \end{bmatrix} \cdot \begin{bmatrix}F_{n-1}\\ F_{n-2} \end{bmatrix} = \begin{bmatrix} 1,1\\ 0,0 \end{bmatrix}^{2} \cdot \begin{bmatrix}F_{n-2}\\ F_{n-3} \end{bmatrix} \cdot \cdot \cdot \cdot =\begin{bmatrix} 1,1\\ 0,0 \end{bmatrix}^{n-1} \cdot \begin{bmatrix}F_{1}\\ F_{0} \end{bmatrix}


我们用矩阵快速幂求出 [ 1 , 1 0 , 0 ] n 1 \begin{bmatrix} 1,1\\ 0,0 \end{bmatrix}^{n-1} 后,结果矩阵的第一行与上面公式中最后的 [ F 1 F 0 ] \begin{bmatrix}F_{1}\\ F_{0} \end{bmatrix} 做矩阵乘法即是最终结果。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define mod 10000
using namespace std;

typedef long long LL;
const int Max_n=100005;

struct Mat{
    int mat[2][2];
};

Mat mul(Mat a,Mat b){
    Mat ans;
    for(int i=0;i<2;i++){
        for(int j=0;j<2;j++){
            ans.mat[i][j]=0;
            for(int k=0;k<2;k++)
                ans.mat[i][j]+=(a.mat[i][k]*b.mat[k][j])%mod;
                ans.mat[i][j]%=mod;
        }
    }
    return ans;
}

Mat q_pow(Mat a,int b){
    Mat ans={1,0,0,1};
    Mat res=a;
    while(b){
        if(b&1) ans=mul(ans,res);
        res=mul(res,res);
        b>>=1;
    }
    return ans;
}
int main(){
    int n;
    while(~scanf("%d",&n)&&n!=-1){
        Mat a={1,1,1,0};
        Mat ans={0,0,0,0};
        ans=q_pow(a,n); 
        printf("%d\n",ans.mat[0][1]);
    }
    return 0;
}

2018年湘潭大学程序设计竞赛 G 又见斐波那契

题目地址:https://ac.nowcoder.com/acm/contest/105/G?&headNav=www&headNav=acm
本题需要注意的点就是矩阵的数据类型,用int中间运算会爆掉,所以构造矩阵的时候需要用 ll
思路:与上面题目套路相同
   X n 1 = [ F n 1 F n 2 i 3 i 2 i 1 ] X_{n-1} = \begin{bmatrix} F_{n-1}\\ F_{n-2} \\ i^{3}\\ i^{2}\\ i\\ 1 \end{bmatrix}    X n = [ F n F n 1 ( i + 1 ) 3 ( i + 1 ) 2 ( i + 1 ) 1 ] X_{n} = \begin{bmatrix} F_{n}\\ F_{n-1} \\ (i+1)^{3}\\ (i+1)^{2}\\ (i+1)\\ 1 \end{bmatrix}    A X n 1 = X n A \cdot X_{n-1} = X_{n}


   [ X , X , X , X , X , X X , X , X , X , X , X X , X , X , X , X , X X , X , X , X , X , X X , X , X , X , X , X X , X , X , X , X , X ] \begin{bmatrix} X,X,X,X,X,X\\ X,X,X,X,X,X\\ X,X,X,X,X,X\\ X,X,X,X,X,X\\ X,X,X,X,X,X\\ X,X,X,X,X,X \end{bmatrix} \cdot [ F n 1 F n 2 ( i + 1 ) 3 ( i + 1 ) 2 i + 1 1 ] \begin{bmatrix}F_{n-1}\\ F_{n-2} \\ (i+1)^{3}\\ (i+1)^{2}\\ i+1\\ 1 \end{bmatrix} = [ F n F n 1 i 3 i 2 i 1 ] = \begin{bmatrix} F_{n}\\ F_{n-1} \\ i^{3}\\ i^{2}\\ i\\ 1 \end{bmatrix}


{ F n = 1 F n 1 + 1 F n 2 + 1 i 3 + 1 i 2 + 1 i + 1 1 F n 1 = 1 F n 1 + 0 F n 2 + 0 i 3 + 0 i 2 + 0 i + 0 1 ( i + 1 ) 3 = 0 F n 1 + 0 F n 2 + 1 i 3 + 3 i 2 + 3 i + 1 1 ( i + 1 ) 2 = 0 F n 1 + 0 F n 2 + 0 i 3 + 1 i 2 + 2 i + 1 1 i + 1 = 0 F n 1 + 0 F n 2 + 0 i 3 + 0 i 2 + 1 i + 1 1 1 = 0 F n 1 + 0 F n 2 + 0 i 3 + 0 i 2 + 0 i + 1 1 \begin{cases} F_{n} = 1 \cdot F_{n-1} + 1 \cdot F_{n-2} + 1 \cdot i^{3} + 1 \cdot i^{2} + 1 \cdot i + 1 \cdot 1\\ F_{n-1} = 1 \cdot F_{n-1} + 0 \cdot F_{n-2} + 0 \cdot i^{3} + 0 \cdot i^{2} + 0 \cdot i + 0 \cdot 1\\ (i+1)^{3} = 0 \cdot F_{n-1} + 0 \cdot F_{n-2} + 1 \cdot i^{3} + 3 \cdot i^{2} + 3 \cdot i + 1 \cdot 1\\ (i+1)^{2} = 0 \cdot F_{n-1} + 0 \cdot F_{n-2} + 0 \cdot i^{3} + 1 \cdot i^{2} + 2 \cdot i + 1 \cdot 1\\ i+1 = 0 \cdot F_{n-1} + 0 \cdot F_{n-2} + 0 \cdot i^{3} + 0 \cdot i^{2} + 1 \cdot i + 1 \cdot 1\\ 1 = 0 \cdot F_{n-1} + 0 \cdot F_{n-2} + 0 \cdot i^{3} + 0 \cdot i^{2} + 0 \cdot i + 1 \cdot 1 \end{cases} = > = > A = [ 1 , 1 , 1 , 1 , 1 , 1 1 , 0 , 0 , 0 , 0 , 0 0 , 0 , 1 , 3 , 3 , 1 0 , 0 , 0 , 1 , 2 , 1 0 , 0 , 0 , 0 , 1 , 1 0 , 0 , 0 , 0 , 0 , 1 ] A = \begin{bmatrix} 1,1,1,1,1,1\\ 1,0,0,0,0,0\\ 0,0,1,3,3,1\\ 0,0,0,1,2,1\\ 0,0,0,0,1,1\\ 0,0,0,0,0,1 \end{bmatrix}


[ F n F n 1 ( i + 1 ) 3 ( i + 1 ) 2 i + 1 1 ] = [ 1 , 1 , 1 , 1 , 1 , 1 1 , 0 , 0 , 0 , 0 , 0 0 , 0 , 1 , 3 , 3 , 1 0 , 0 , 0 , 1 , 2 , 1 0 , 0 , 0 , 0 , 1 , 1 0 , 0 , 0 , 0 , 0 , 1 ] [ F n 1 F n 2 i 3 i 2 i 1 ] = [ 1 , 1 , 1 , 1 , 1 , 1 1 , 0 , 0 , 0 , 0 , 0 0 , 0 , 1 , 3 , 3 , 1 0 , 0 , 0 , 1 , 2 , 1 0 , 0 , 0 , 0 , 1 , 1 0 , 0 , 0 , 0 , 0 , 1 ] 2 [ F n 2 F n 3 ( i 1 ) 3 ( i 1 ) 2 i 1 1 ] = = [ 1 , 1 , 1 , 1 , 1 , 1 1 , 0 , 0 , 0 , 0 , 0 0 , 0 , 1 , 3 , 3 , 1 0 , 0 , 0 , 1 , 2 , 1 0 , 0 , 0 , 0 , 1 , 1 0 , 0 , 0 , 0 , 0 , 1 ] n 1 [ F 1 F 0 2 3 2 2 2 1 ] \begin{bmatrix} F_{n}\\ F_{n-1} \\ (i+1)^{3}\\ (i+1)^{2}\\ i+1\\ 1 \end{bmatrix} = \begin{bmatrix} 1,1,1,1,1,1\\ 1,0,0,0,0,0\\ 0,0,1,3,3,1\\ 0,0,0,1,2,1\\ 0,0,0,0,1,1\\ 0,0,0,0,0,1 \end{bmatrix} \cdot \begin{bmatrix}F_{n-1}\\ F_{n-2} \\ i^{3}\\ i^{2}\\ i\\ 1 \end{bmatrix} = \begin{bmatrix} 1,1,1,1,1,1\\ 1,0,0,0,0,0\\ 0,0,1,3,3,1\\ 0,0,0,1,2,1\\ 0,0,0,0,1,1\\ 0,0,0,0,0,1 \end{bmatrix}^{2} \cdot \begin{bmatrix}F_{n-2}\\ F_{n-3} \\ (i-1)^{3}\\ (i-1)^{2}\\ i-1\\ 1 \end{bmatrix} = \cdot \cdot \cdot \cdot = \begin{bmatrix} 1,1,1,1,1,1\\ 1,0,0,0,0,0\\ 0,0,1,3,3,1\\ 0,0,0,1,2,1\\ 0,0,0,0,1,1\\ 0,0,0,0,0,1 \end{bmatrix}^{n - 1} \cdot \begin{bmatrix}F_{1}\\ F_{0} \\ 2^{3}\\ 2^{2}\\ 2\\ 1 \end{bmatrix}


最后求出 A n 1 A^{n-1} 后,与公式中最后的行列式相乘即可。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

typedef long long LL;
const int mod=1000000007;
const int Max_n=500005;
int x[6]={1,0,8,4,2,1};

struct Mat{
    LL mat[6][6];
};

Mat mul(Mat a,Mat b){
    Mat z;
    for(int i=0;i<6;i++){
        for(int j=0;j<6;j++){
            z.mat[i][j]=0;
            for(int k=0;k<6;k++){
                z.mat[i][j]+=(a.mat[i][k]*b.mat[k][j])%mod;
                z.mat[i][j]%=mod;
            }
        }
    }
    return z;
}
Mat q_pow(Mat a,LL b){
    Mat ans={
        1,0,0,0,0,0,
        0,1,0,0,0,0,
        0,0,1,0,0,0,
        0,0,0,1,0,0,
        0,0,0,0,1,0,
        0,0,0,0,0,1,
    };
    Mat res=a;
    while(b){
        if(b&1) ans=mul(ans,res);
        res=mul(res,res);
        b>>=1;
    }
    return ans;
}

int main(){
    Mat a={
        1,1,1,1,1,1,
        1,0,0,0,0,0,
        0,0,1,3,3,1,
        0,0,0,1,2,1,
        0,0,0,0,1,1,
        0,0,0,0,0,1
    };
    int t;
    scanf("%d",&t);
    while(t--){
        LL n;
        scanf("%lld",&n);
        if(n==1){
            printf("1\n");
            continue;
        }
        if(n==0){
            printf("0\n");
            continue;
        }
        Mat ans=q_pow(a,n-1);
        int res=0;
        for(int i=0;i<6;i++){
            res+=(ans.mat[0][i]*x[i])%mod;
            res%=mod;
        }
        printf("%d\n",res);
    }
    return 0;
}
发布了166 篇原创文章 · 获赞 68 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_42217376/article/details/102090048