P1349 广义斐波那契数列(矩阵加速)

时间:2023-03-09 18:18:00
P1349 广义斐波那契数列(矩阵加速)

P1349 广义斐波那契数列

题目描述

广义的斐波那契数列是指形如an=pan-1+qan-2的数列。今给定数列的两系数p和q,以及数列的最前两项a1和a2,另给出两个整数n和m,试求数列的第n项an除以m的余数。

输入输出格式

输入格式:

输入包含一行6个整数。依次是p,q,a1,a2,n,m,其中在p,q,a1,a2整数范围内,n和m在长整数范围内。

输出格式:

输出包含一行一个整数,即an除以m的余数。

输入输出样例

输入样例#1:

1 1 1 1 10 7

输出样例#1:

6

说明

数列第10项是55,除以7的余数为6。

简单的矩阵加速

推导很好推吧

两项式一般也就\(2*2\)矩阵

自己手玩一下就能推出来

\[\begin{pmatrix} a[n],a[n-1] \end{pmatrix}=\begin{pmatrix} a[n-1],a[n-2]\end{pmatrix} \times \begin{bmatrix} p,1\\q,0 \end{bmatrix}
\]

从而可以得到

\[\begin{pmatrix} a[n],a[n-1] \end{pmatrix}=\begin{pmatrix} a[2],a[1]\end{pmatrix} \times \begin{bmatrix} p,1\\q,0 \end{bmatrix}^{n-2}
\]
#include <iostream>
#include <cstdio>
#define int long long
using namespace std;
struct node {
int m[40][40];
}a,b;
int mod;
node mul(node x,node y) {
node c= {};
for(int i=1; i<=2; ++i)
for(int j=1; j<=2; ++j)
for(int k=1; k<=2; ++k)
c.m[i][j]=(c.m[i][j]+(x.m[i][k]*y.m[k][j])%mod)%mod;
return c;
}
node fpow(node ss,int p) {
node ans= {};
ans.m[1][1]=ans.m[2][2]=1;
while(p) {
if(p&1) ans=mul(ans,ss);
ss=mul(ss,ss);
p>>=1;
}
return ans;
}
int p,q,n;
main() {
cin>>b.m[1][1]>>b.m[2][1]>>a.m[1][2]>>a.m[1][1]>>n>>mod;
b.m[1][2]=1;
if(n==1||n==2) {
cout<<a.m[n][1]<<"\n";
return 0;
}
b=fpow(b,n-2);
a=mul(a,b);
cout<<a.m[1][1]<<"\n";
return 0;
}