广义斐波那契数列
我们知道,关于数列一类的题目我们可以通过矩阵来进行加速了,我要用这这个题讲一讲矩阵的乘法和和加法
事实上对于一个数竞党来说,看到这题第一眼时,我想到了二阶项递推(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} \]