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)矩阵
自己手玩一下就能推出来
[egin{pmatrix} a[n],a[n-1] end{pmatrix}=egin{pmatrix} a[n-1],a[n-2]end{pmatrix} imes egin{bmatrix} p,1\q,0 end{bmatrix}
]
从而可以得到
[egin{pmatrix} a[n],a[n-1] end{pmatrix}=egin{pmatrix} a[2],a[1]end{pmatrix} imes egin{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]<<"
";
return 0;
}
b=fpow(b,n-2);
a=mul(a,b);
cout<<a.m[1][1]<<"
";
return 0;
}