洛谷P1939 【模板】矩阵加速(数列)
题意
$a_1=a_2=a_3=1$
$a_n=a_{n-3}+a_{n-1}\quad(n>3)$
有$T$组询问。对每组询问,给定$n$,求$a_n\mod 1000000007$。
$T\leq 100,n\leq 2\times 10^9$。
题解
首先假定你会矩阵快速幂(不会的看:这里)
那么,我们可以构造列向量
$$C_{n}=\begin{bmatrix}a_{n-2}\\a_{n-1}\\a_{n}\end{bmatrix}$$
,然后想办法构造一个$3x3$的矩阵$A$,使得
$$A\times C_{n}=C_{n+1}$$
显然,$A$可以等于
$$\begin{bmatrix}0&1&0\\0&0&1\\1&0&1\end{bmatrix}$$
然后矩阵快速幂一波就可以在$\mathcal O(\lg n)$的时间内求出$a_{n}$了。
贴代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef array<array<ll, 4>, 4> Matrix;
const ll P = 1000000007;
ll n, k;
Matrix A, I;
Matrix MatrixMul(const Matrix &A, const Matrix &B) {
Matrix ret;
for (int i=1; i<=n; i++)
for (int j=1; j<=n; j++) {
ret[i][j] = 0;
for (int k=1; k<=n; k++)
(ret[i][j] += A[i][k] * B[k][j] % P) %= P;
}
return ret;
}
Matrix PowerMod(ll k) {
if (k == 0) return I;
if (k == 1) return A;
if (k & 1) return MatrixMul(PowerMod(k-1), A);
Matrix B = PowerMod(k >> 1);
return MatrixMul(B, B);
}
signed main() {
int T; scanf("%d", &T);
n = 3; I[1][1] = I[2][2] = I[3][3] = 1;
A[1][2] = A[2][3] = A[3][1] = A[3][3] = 1;
while (T--) {
int n; scanf("%d", &n);
if (n <= 3) puts("1");
else {
Matrix ret = PowerMod(n - 3);
printf("%lld\n", (ret[3][1] + ret[3][2] + ret[3][3]) % P);
}
}
return 0;
}

浙公网安备 33010602011771号