题解 SP8001 【FIBOSUM - Fibonacci Sum】

rui_er

2020-08-18 14:17:01

Solution

我也不知道我怎么找到的这题,但是既然 AC 了,就来写一篇题解。 题意简述:共 $T$ 组询问,每次读入两个数 $n,m$,输出 $\displaystyle\sum_{i=n}^ma_i\mod (10^9+7)$ 的值,其中 $a_i$ 为斐波那契数。 --- 由于洛谷爬的时候漏掉了数据范围,可以到原题目中查看:$T\le 10^3,0 \le n\le m\le 10^9$,可以看到暴力求出所有斐波那契数的前缀和后求解显然会超时,容易想到矩阵加速。 我们使用矩阵维护第 $i$ 项、第 $i+1$ 项的值及前 $i$ 项的和,下面考虑构造转移矩阵。 根据斐波那契数列的定义,我们知道: $$\begin{cases}a_{i+1}=&a_{i+1}\\a_{i+2}=&a_{i}+a_{i+1}\\s_{i+1}=&s_i+a_{i+1}\end{cases}$$ 经过一些简单变换即可得到转移矩阵: $$\begin{bmatrix}a_i&a_{i+1}&s_i\end{bmatrix}\times\begin{bmatrix}0&1&0\\1&1&1\\0&0&1\end{bmatrix}=\begin{bmatrix}a_{i+1}&a_{i+2}&s_{i+1}\end{bmatrix}$$ 此时,我们可以通过类似于题目[矩阵加速](/problem/P1939)的方式利用矩阵快速幂在 $\log$ 时间内求出对于一个整数 $k$ 的 $s_k$ 的值。我们要求的答案即为 $s_m-s_{n-1}\mod (10^9+7)$。 代码: ```cpp //By: Luogu@rui_er(122461) #include <bits/stdc++.h> using namespace std; typedef long long ll; const ll mod = 1e9+7; ll T, n, m; struct Matrix { ll id[4][4]; Matrix() {} Matrix(int x, int y, int z) {id[1][1]=x;id[1][2]=y;id[1][3]=z;} ~Matrix() {} void clear() {memset(id, 0, sizeof(id));} void init(ll k) {clear(); for(ll i=1;i<=k;i++) id[i][i] = 1;} }a, b; Matrix operator * (const Matrix &a, const Matrix &b) { Matrix c; c.clear(); for(ll i=1;i<=3;i++) for(ll j=1;j<=3;j++) for(ll k=1;k<=3;k++) c.id[i][j] = (c.id[i][j] + a.id[i][k] * b.id[k][j] % mod) % mod; return c; } Matrix operator ^ (Matrix &a, ll k) { Matrix res; res.init(3); for(;k;k>>=1,a=a*a) if(k&1) res = res * a; return res; } Matrix calc(ll k) { if(k <= 0) return Matrix(0, 0, 0); if(k == 1) return Matrix(0, 1, 1); if(k == 2) return Matrix(1, 1, 2); a.clear(); b.clear(); a.id[1][1] = a.id[1][2] = a.id[1][3] = 1; b.id[1][2] = b.id[2][1] = b.id[2][2] = b.id[2][3] = b.id[3][3] = 1; a = a * (b ^ (k - 1)); return a; } int main() { scanf("%lld", &T); while(T--) { scanf("%lld%lld", &n, &m); printf("%lld\n", (calc(m).id[1][3]%mod-calc(n-1).id[1][3]%mod+mod)%mod); } return 0; } ```