问题分析
对于给定的递推数列 (
),其本质是一个高阶(三阶)常系数线性齐次递推关系。
- 时间复杂度瓶颈:查询数量
,项数
。若采用传统的动态规划进行
的线性递推,单次查询最高将达到
次运算,总运算量达
,这会引发严重的超时。
- 空间复杂度限制:由于
极大,若尝试采用空间换时间(预处理并存储所有结果),将需要约
的连续内存(假设使用 32 位整型),这必然导致内存超限。
- 数据溢出风险:由于数列呈指数级变大,且要求对
取模,在任何涉及加法或乘法的算术操作中,不仅最终结果需要取模,中间运算过程也会迅速突破 32 位整型的上限,必须在所有子操作中严格应用模运算律。
算法:矩阵快速幂
针对超大项数的常系数线性递推问题,矩阵快速幂是唯一的工业级标准解法。它将线性的递推过程转化为矩阵的幂运算,从而利用“快速幂”算法的倍增思想,将线性时间复杂度降维至对数时间复杂度。
状态空间的矩阵化
设状态列向量 ,我们需要构造一个状态转移矩阵
,使得
。
根据递推公式:
由此抽离出 的转移矩阵
:
状态转移通项
已知基础状态为 时的值,提取基础列向量
:
根据矩阵的结合律,对于任意 ,可推导出状态列向量通式:
目标值 即为结果列向量
的第一行元素。
复杂度分析
- 时间复杂度:
。其中
为矩阵维度(本题
)。两个
矩阵相乘耗时
,指数递减需
步。完全满足 1 秒执行完毕的性能要求。
- 空间复杂度:
。整个计算生命周期内仅需维护常量个
的矩阵,空间开销可忽略不计。
代码实现
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
static constexpr int MOD = 1e9 + 7;
struct Matrix {
array<array<ll, 3>, 3> data{};
// 单位矩阵
static Matrix identity() {
Matrix res;
for (int i = 0; i < 3; i++)
res.data[i][i] = 1;
return res;
}
Matrix operator*(const Matrix& other) const {
Matrix res;
for (int i = 0; i < 3; i++) {
for (int k = 0; k < 3; k++) {
if (data[i][k] == 0)
continue;
for (int j = 0; j < 3; j++) {
res.data[i][j] = (res.data[i][j] + data[i][k] * other.data[k][j]) % MOD;
}
}
}
return res;
}
};
template <typename T>
T power(T base, ll exp) {
T res = T::identity();
while (exp > 0) {
if (exp & 1)
res = res * base;
base = base * base;
exp >>= 1;
}
return res;
}
void solve() {
int n;
cin >> n;
if (n <= 3) {
cout << 1 << "\n";
return;
}
Matrix T;
T.data = {{
{1, 0, 1},
{1, 0, 0},
{0, 1, 0}
}
};
auto res = power(T, n - 3);
ll ans = 0;
for (int j = 0; j < 3; j++) {
ans = (ans + res.data[0][j]) % MOD;
}
cout << ans << "\n";
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while (T--) {
solve();
}
return 0;
}

京公网安备 11010502036488号