【SP8001】Fibonacci Sum
斐波那契数列是一个人们所熟知的序列,不多赘述。
直接求题面中给出的 \(\sum\limits_{i=N}^MF_i\) 似乎很没有思路,我们运用前缀和的思想,得到 \(\sum\limits_{i=N}^MF_i=\left(\sum\limits_{i=1}^MF_i\right)-\left(\sum\limits_{i=1}^{N-1}F_i\right)\),容易发现,右边这两坨形式是一样的。
问题转化成求形如 \(\sum\limits_{i=1}^{n} F_i\) 的值。
我们来推个式子:
\[\begin{aligned}
&\; \; \; \; \; F_{n} \\
&= F_{n-1}+F_{n-2} \\
&= F_{n-2}+F_{n-3}+F_{n-4}+F_{n-3}\\
&= F_{n-2}+F_{n-3}+F_{n-4}+F_{n-5}+F_{n-6}+F_{n-5}\\
&= \cdots
\end{aligned}
\]
不难发现,经过有限次推导,式子最后一项会变成 \(F_1\) 或 \(F_2\)。
又有 \(F_1=F_2=1\),则得到式子 \(F_n=\left(\sum\limits_{i=1}^{n-2}F_{i}\right)+1\)。
则回到要求的式子,\(\sum\limits_{i=1}^nF_i=F_{n+2}-1\)。
通过矩阵快速幂优化递推,我们可以在 \(O(\log n)\) 的复杂度内求出 \(F_{n+2}\),减一后得到结果。
再将此带回最原始的式子,问题得解。
#include <stdio.h>
#include <string.h>
const int MAXN=2,mod=1000000007;
template<const size_t n=MAXN>class Matrix
{
private:
int i,j,k;
long long temp[n][n];
public:
long long f[n][n];
Matrix()
{
for(i=0;i<n;++i)
for(j=0;j<n;++j)
{
f[i][j]=i==j;
}
}
inline const Matrix &operator*=(const Matrix &other)
{
for(i=0;i<n;++i)
for(j=0;j<n;++j)
{
temp[i][j]=0;
}
for(i=0;i<n;++i)
for(j=0;j<n;++j)
for(k=0;k<n;++k)
(temp[i][j]+=f[i][k]*other.f[k][j])%=mod;
for(i=0;i<n;++i)
for(j=0;j<n;++j)
{
f[i][j]=temp[i][j];
}
return *this;
}
};
long long get(long long x){
int t;
long long X;
if(x<3)
return 1;
else{
Matrix<MAXN> ans;
Matrix<MAXN> base;
base.f[0][0]=1;base.f[0][1]=1;
base.f[1][0]=1;base.f[1][1]=0;
ans.f[0][0]=ans.f[0][1]=1;
X=x-2;
while(X){
if(X&1)
ans*=base;
base*=base;
X>>=1;
}
return ans.f[0][0];
}
}
int main()
{long long n,m;
int t;scanf("%d",&t);
while(t--)
{
scanf("%lld %lld",&n,&m);
printf("%lld\n",((get(m+2)-1)-((get(n+1)-1))%mod+mod)%mod);
}
return 0;
}