题意
给出一个序列AAA,我们知道:
A1=A2=A3=1A_1=A_2=A_3=1A1=A2=A3=1
AN=AN−1+AN−3A_N=A_{N-1}+A_{N-3}AN=AN−1+AN−3
有TTT次询问,求ANA_NAN。
思路
我们可以设一个矩阵AAA为:
[AN−3AN−2AN−1]\begin{bmatrix}
A_{N-3}&A_{N-2}&A_{N-1}
\end{bmatrix}[AN−3AN−2AN−1]
那么我们要把这个矩阵变成:
[AN−2AN−1AN]\begin{bmatrix}
A_{N-2}&A_{N-1}&A_{N}
\end{bmatrix}[AN−2AN−1AN]
我们就可以乘上这个矩阵:
[001100011]\begin{bmatrix}
0&0&1 \\
1&0&0 \\
0&1&1
\end{bmatrix}⎣⎡010001101⎦⎤
然后我们就可以做了,特判N<3N<3N<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");
}
}