题意
给出一个序列
A
A
A,我们知道:
A
1
=
A
2
=
A
3
=
1
A_1=A_2=A_3=1
A1=A2=A3=1
A
N
=
A
N
−
1
+
A
N
−
3
A_N=A_{N-1}+A_{N-3}
AN=AN−1+AN−3
有
T
T
T次询问,求
A
N
A_N
AN。
思路
我们可以设一个矩阵
A
A
A为:
[
A
N
−
3
A
N
−
2
A
N
−
1
]
\begin{bmatrix} A_{N-3}&A_{N-2}&A_{N-1} \end{bmatrix}
[AN−3AN−2AN−1]
那么我们要把这个矩阵变成:
[
A
N
−
2
A
N
−
1
A
N
]
\begin{bmatrix} A_{N-2}&A_{N-1}&A_{N} \end{bmatrix}
[AN−2AN−1AN]
我们就可以乘上这个矩阵:
[
0
0
1
1
0
0
0
1
1
]
\begin{bmatrix} 0&0&1 \\ 1&0&0 \\ 0&1&1 \end{bmatrix}
⎣⎡010001101⎦⎤
然后我们就可以做了,特判
N
<
3
N<3
N<3
代码
#include<cstdio>
#include<cstring>
const int mod = 1e9 + 7;
int T, N;
struct matrix{
int a[4][4];
};
matrix operator *(matrix &a, matrix &b){
matrix c;
memset(c.a, 0, sizeof(c.a));
for (int i = 1; i <= 3; i++)
for (int j = 1; j <= 3; j++)
for (int k = 1; k <= 3; k++)
c.a[i][j] = (c.a[i][j] + (long long)a.a[i][k] * b.a[k][j]) % mod;
return c;
}
void ksm(int b) {
matrix A;
memset(A.a, 0, sizeof(A.a));
A.a[1][3] = 1;
A.a[2][1] = 1;
A.a[3][2] = 1;
A.a[3][3] = 1;
matrix r = A;
for (; b; b >>= 1) {
if (b & 1) r = r * A;
A = A * A;
}
int ans[4];
memset(ans, 0, sizeof(ans));
for (int j = 1; j <= 3; j++)
for (int k = 1; k <= 3; k++)
ans[j] = (ans[j] + r.a[k][j]) % mod;
printf("%d\n", ans[3]);
}
int main() {
scanf("%d", &T);
for (; T; T--) {
scanf("%d", &N);
if (N > 3)
ksm(N - 4);
else printf("1\n");
}
}