[洛谷1349] 广义斐波那契数列

广义斐波那契数列

题目

我们知道,关于数列一类的题目我们可以通过矩阵来进行加速了,我要用这这个题讲一讲矩阵的乘法和和加法

事实上对于一个数竞党来说,看到这题第一眼时,我想到了二阶项递推(qvq)。

然后但是对于幂次来说,精度损失无法接受。qwq。

哦哦。按照我们斐波那契的操作,于是有矩阵
\[ \begin{bmatrix} a_n&a_{n-1} \end{bmatrix} = \begin{bmatrix} a_{2}&a_{1} \end{bmatrix} \times \begin{bmatrix} p&1\\ q&0 \end{bmatrix}^{n-2} \]
我们这么搞得原因是 \(a_n=p \times a_{n-1}+q\times a_{n-2}\)

这怕不是我最短的矩阵快速幂 qvq

#include <cstdio>
typedef long long ll;
ll a1,a2,n,m,p,q;
struct Mat{
    ll a[2][2];
    Mat mul(Mat t){
        Mat tmp(0,0,0,0);
        tmp.a[0][0]=(a[0][0]*t.a[0][0]+a[0][1]*t.a[1][0])%m;tmp.a[0][1]=(a[0][0]*t.a[0][1]+a[0][1]*t.a[1][1])%m;
        tmp.a[1][0]=(a[1][0]*t.a[0][0]+a[1][1]*t.a[1][0])%m;tmp.a[1][1]=(a[1][0]*t.a[0][1]+a[1][1]*t.a[1][1])%m;
        return tmp;
    }
    void operator = (const Mat &x){a[0][0]=x.a[0][0];a[0][1]=x.a[0][1];a[1][0]=x.a[1][0];a[1][1]=x.a[1][1];}
    Mat(ll x,ll y,ll z,ll w){a[0][0]=x,a[0][1]=y,a[1][0]=z,a[1][1]=w;}
    Mat pow(ll u){
        if(u==1) return Mat(a[0][0],a[0][1],a[1][0],a[1][1]);
        Mat aa=pow(u/2);
        return u%2?aa.mul(aa.mul(Mat(a[0][0],a[0][1],a[1][0],a[1][1]))):aa.mul(aa);
    }
};
int main(){
    scanf("%lld%lld%lld%lld%lld%lld",&p,&q,&a1,&a2,&n,&m); 
    Mat a=Mat(p,1,q,0).pow(n-2);Mat p=Mat(a2,a1,a1,0).mul(a);printf("%lld",p.a[0][0]);
    return 0;
}

我们简单的说一下矩阵乘法(加法是送的好吗
\[ 存在 A是 m \times n的矩阵 ,B是 n \times p的矩阵,则有 C=A \times B \\此时 C是一个 m\times p的矩阵 且 c_{ij}=\sum_{k=1}^n a_{ik}\times b_{kj} \]

猜你喜欢

转载自www.cnblogs.com/zhltao/p/12376748.html