广义斐波那契数列
题目描述
广义的斐波那契数列是指形如
a
n
=
p
×
a
n
−
1
+
q
×
a
n
−
2
a_n=p\times a_{n-1}+q\times a_{n-2}
an=p×an−1+q×an−2 的数列。
今给定数列的两系数
p
p
p 和
q
q
q,以及数列的最前两项
a
1
a_1
a1 和$ a_2$,另给出两个整数
n
n
n 和
m
m
m,试求数列的第
n
n
n 项
a
n
m
o
d
m
a_n \bmod m
anmodm。
输入格式
输入包含一行六个整数, p , q , a 1 , a 2 , n , m p,q,a_1,a_2,n,m p,q,a1,a2,n,m。
输出格式
输出包含一行一个整数表示答案。
样例 #1
样例输入 #1
1 1 1 1 10 7
样例输出 #1
6
提示
数列第 $10 $项是 55 55 55, 55 m o d 7 = 6 55 \bmod 7 = 6 55mod7=6。
【数据范围】
对于
100
%
100\%
100% 的数据,
p
,
q
,
a
1
,
a
2
∈
[
0
,
2
31
−
1
]
p,q,a_1,a_2 \in [0,2^{31}-1]
p,q,a1,a2∈[0,231−1],
1
≤
n
,
m
≤
2
31
−
1
1\le n,m \le 2^{31}-1
1≤n,m≤231−1。
1、矩阵乘法, 矩阵快速幂
(f[2], f[3]) = (f[1], f[2]) * A, A 是矩阵,
A[1][1]=0 A[1][2]=q
A[2][1]=1 A[2][2]=p
2、 n >= 3 时候, (f[n-1], f[n]) = (f[1], f[2]) * A^(n-2)
先算出 A^(n-2), 最后结果就是
f[n] = f[1] * A[1][2] + f[2] * A[2][2]
3、 全部数据用 long long , 一步到位
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
typedef long long ll;
ll p, q, a1, a2, n, mod;
struct matrix
{
ll c[3][3];
matrix()
{
memset(c, 0, sizeof c);
}
};
matrix R;
matrix multi(matrix& x, matrix& y)
{
matrix r;
for(int i = 1; i <= 2; ++i)
{
for(int j = 1; j <= 2; ++j)
{
for(int k = 1; k <= 2; ++k)
{
r.c[i][j] += (x.c[i][k] % mod) * (y.c[k][j] % mod) % mod;
r.c[i][j] %= mod;
}
}
}
return r;
}
matrix quick_pow(matrix A, ll k)
{
matrix res;
for(int i = 1; i <= 2; ++i)
res.c[i][i] = 1;
while(k)
{
if(k & 1)
{
res = multi(res, A);
}
A = multi(A, A);
k >>= 1;
}
return res;
}
int main()
{
scanf("%lld%lld%lld%lld%lld%lld", &p, &q, &a1, &a2, &n, &mod);
if(n == 1)
{
printf("%lld\n", a1 % mod);
return 0;
}
if(n == 2)
{
printf("%lld\n", a2 % mod);
return 0;
}
R.c[1][1] = 0, R.c[1][2] = q, R.c[2][1] = 1, R.c[2][2] = p;
R = quick_pow(R, n - 2);
ll t1 = ((R.c[1][2] % mod) * (a1 % mod)) % mod;
ll t2 = ((R.c[2][2] % mod) * (a2 % mod)) % mod;
ll ans = (t1 + t2) % mod;
printf("%lld\n", ans);
return 0;
}
/*
1 1 1 1 10 7
*/
/*
6
*/