题目
描述
TR非常喜欢数学,经常一个人拿出草稿纸研究奇奇怪怪的数学问题,最近,他突然对数列产生了兴趣,他找到一个数列,类似于斐波拉契,即:
T
n
=
1
∗
f
1
+
2
∗
f
2
+
3
∗
f
3
+
…
+
n
∗
f
n
T_n=1*f_1+2*f_2+3*f_3+…+n*f_n
Tn=1∗f1+2∗f2+3∗f3+…+n∗fn (fn为斐波拉契的第n项值)现在TR想请你帮忙求Tn%m的值
输入
两个用空格隔开的整数
n
n
n和
m
m
m,
1
≤
n
,
m
≤
2
31
−
1
1 \leq n,m \leq2^{31}-1
1≤n,m≤231−1
输出
T
n
(
m
o
d
m
)
T_n \pmod m
Tn(modm)的值
样例输入
5 5
样例输出
1
思路
按照矩阵的常规递推求和思路尿性 ,首先在原矩阵中定义一个
T
T
T来表示和,至于下标是多少,待会再来定吧,再看,我们肯定要递推一下斐波那契,所以还要定义两个f,来递推斐波。要得到T,肯定要得到i*f[i],我们定
q
[
i
]
=
i
∗
f
[
i
]
q[i] = i*f[i]
q[i]=i∗f[i],则有
q
[
i
]
=
i
∗
f
[
i
]
,
q
[
i
−
1
]
=
(
i
−
1
)
∗
f
[
i
−
1
]
,
q
[
i
−
2
]
=
(
i
−
2
)
∗
f
[
i
−
2
]
q[i]=i*f[i],q[i-1]=(i-1)*f[i-1],q[i-2]=(i-2)*f[i-2]
q[i]=i∗f[i],q[i−1]=(i−1)∗f[i−1],q[i−2]=(i−2)∗f[i−2]我们来递推一下
q
[
i
]
,
q
[
i
−
1
]
,
q
[
i
−
2
]
q[i],q[i-1],q[i-2]
q[i],q[i−1],q[i−2]的关系,
q
[
i
−
1
]
+
q
[
i
−
2
]
=
(
i
−
1
)
∗
f
[
i
−
1
]
+
(
i
−
2
)
∗
f
[
i
−
2
]
=
q[i-1]+q[i-2]=(i-1)*f[i-1]+(i-2)*f[i-2]=
q[i−1]+q[i−2]=(i−1)∗f[i−1]+(i−2)∗f[i−2]=
(
i
−
2
)
∗
(
f
[
i
−
1
]
+
f
[
i
−
2
]
)
+
f
[
i
−
1
]
=
(
i
−
2
)
∗
f
[
i
]
+
f
[
i
−
1
]
(i-2)*(f[i-1]+f[i-2])+f[i-1]=(i-2)*f[i]+f[i-1]
(i−2)∗(f[i−1]+f[i−2])+f[i−1]=(i−2)∗f[i]+f[i−1]
我们要得到
i
∗
f
[
i
]
i*f[i]
i∗f[i],是不是就要减去
f
[
i
−
1
]
f[i-1]
f[i−1]再加上
2
∗
f
[
i
]
2*f[i]
2∗f[i],所以,递推式就很清楚了
q
[
i
]
=
q
[
i
−
1
]
+
q
[
i
−
2
]
−
f
[
i
−
1
]
+
2
∗
f
[
i
]
q[i]=q[i-1]+q[i-2]-f[i-1]+2*f[i]
q[i]=q[i−1]+q[i−2]−f[i−1]+2∗f[i]
所以原矩阵中我们需要
f
[
i
]
和
f
[
i
−
1
]
f[i]和f[i-1]
f[i]和f[i−1],有了它们俩,我们要递推出
q
[
i
]
q[i]
q[i],是不是还要
q
[
i
−
2
]
和
q
[
i
−
1
]
q[i-2]和q[i-1]
q[i−2]和q[i−1],而
T
[
i
−
1
]
=
T
[
i
−
2
]
+
q
[
i
−
1
]
T[i-1]=T[i-2]+q[i-1]
T[i−1]=T[i−2]+q[i−1],所以原矩阵就为
[
T
n
−
2
,
q
n
−
2
,
q
n
−
1
,
f
n
−
1
,
f
n
]
\begin{bmatrix}T_{n-2},q_{n-2},q_{n-1},f_{n-1},f_{n} \end{bmatrix}
[Tn−2,qn−2,qn−1,fn−1,fn]
而我们要乘的矩阵就为
[
1
,
0
,
0
,
0
,
0
0
,
0
,
1
,
0
,
0
1
,
1
,
1
,
0
,
0
0
,
0
,
−
1
,
0
,
1
0
,
0
,
2
,
1
,
1
]
\begin{bmatrix} 1,0,0,0,0\\ 0,0,1,0,0\\ 1,1,1,0,0\\ 0,0,-1,0,1\\ 0,0,2,1,1\\ \end{bmatrix}
⎣⎢⎢⎢⎢⎡1,0,0,0,00,0,1,0,01,1,1,0,00,0,−1,0,10,0,2,1,1⎦⎥⎥⎥⎥⎤
快速幂一下就行了
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define LL long long
int n, m;
struct Mx{
int x, y;
LL a[9][9];
void cl(){
memset(a, 0, sizeof(a));
return ;
}
Mx operator * (const Mx &r)const{
Mx p;
for(int i = 1; i <= x; i ++){
for(int j = 1; j <= r.y; j ++){
p.a[i][j] = 0;
for(int k = 1; k <= y; k++)
p.a[i][j]=(p.a[i][j]+a[i][k]*r.a[k][j]%m)%m;
}
}
p.x = x, p.y = r.y;
return p;
}
}A, F;
Mx qkp(Mx b, int y){
Mx sum;
sum.cl();
sum.x = sum.y = b.y;
for(int i = 1; i < 6; i ++)
sum.a[i][i] = 1;
while( y ){
if( y&1 )
sum = sum * b;
b = b * b;
y >>= 1;
}
return sum;
}
int main(){
scanf("%d%d", &n, &m);
F.x = 1, F.y = 5;
F.a[1][1] = 1, F.a[1][2] = 1;
F.a[1][3] = 2, F.a[1][4] = 1;
F.a[1][5] = 2;
A.cl();
A.x = A.y = 5;
A.a[1][1] = A.a[2][3] = A.a[3][1] = A.a[3][2] = A.a[3][3] = 1;
A.a[4][3] = -1;
A.a[5][3] = 2;
A.a[4][5] = A.a[5][4] = A.a[5][5] = 1;
A = qkp(A, n-1);
F = F * A;
printf("%lld\n", F.a[1][1]%m);
return 0;
}