解法一
找规律不难发现斐波那契数列的前缀和和斐波那契数列有直接的联系,也就是 s ( n ) = f ( n + 2 ) − 1 s(n)=f(n+2)-1 s(n)=f(n+2)−1,这个可以通过数学归纳法证明或者通过斐波那契数列的公式 f ( n ) = 1 5 [ ( 1 + 5 2 ) n − ( 1 − 5 2 ) n ] f(n)=\frac{1}{\sqrt{5}}[(\frac{1+\sqrt{5}}{2})^n-(\frac{1-\sqrt{5}}{2})^n] f(n)=51[(21+5)n−(21−5)n],然后考虑等比数列求和公式
code:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int Mod=1e9+7;
struct Matrix{
ll matrix[105][105];
};
int n;
Matrix mul(Matrix a,Matrix b){
Matrix ans;
memset(ans.matrix,0,sizeof ans.matrix);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int k=1;k<=n;k++){
ans.matrix[i][j]+=a.matrix[i][k]*b.matrix[k][j]%Mod;
ans.matrix[i][j]%=Mod;
}
return ans;
}
Matrix qkp(Matrix mx,ll x){
Matrix ans;
memset(ans.matrix,0,sizeof ans.matrix);
for(int i=1;i<=n;i++) ans.matrix[i][i]=1;
while(x){
if(x&1) ans=mul(ans,mx);
mx=mul(mx,mx);
x>>=1;
}
return ans;
}
int main(){
ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int t,l,r;
Matrix mx;
n=2;
mx.matrix[1][1]=1,mx.matrix[1][2]=1;
mx.matrix[2][1]=1,mx.matrix[2][2]=0;
cin>>t;
while(t--){
cin>>l>>r;
r+=2,l+=2;
Matrix res1=qkp(mx,r),res2=qkp(mx,l-1);
cout<<(res1.matrix[2][1]-res2.matrix[2][1]+Mod)%Mod<<endl;
}
return 0;
}
解法二
我们可以得到关于斐波那契前缀和的这样一个递推式:
s ( n ) = s ( n − 1 ) + f ( n ) = s ( n − 1 ) + f ( n − 1 ) + f ( n − 2 ) = s ( n − 1 ) + s ( n − 1 ) − s ( n − 3 ) = 2 ∗ s ( n − 2 ) − s ( n − 3 ) s(n)=s(n-1)+f(n)=s(n-1)+f(n-1)+f(n-2)=s(n-1)+s(n-1)-s(n-3)=2*s(n-2)-s(n-3) s(n)=s(n−1)+f(n)=s(n−1)+f(n−1)+f(n−2)=s(n−1)+s(n−1)−s(n−3)=2∗s(n−2)−s(n−3)
即: s ( n ) = 2 ∗ s ( n − 1 ) + 0 ∗ s ( n − 2 ) − 1 ∗ s ( n − 3 ) s(n)=2*s(n-1)+0*s(n-2)-1*s(n-3) s(n)=2∗s(n−1)+0∗s(n−2)−1∗s(n−3)
然后又因为:
s ( n − 1 ) = 1 ∗ s ( n − 1 ) + 0 ∗ s ( n − 2 ) + 0 ∗ s ( n − 3 ) s(n-1)=1*s(n-1)+0*s(n-2)+0*s(n-3) s(n−1)=1∗s(n−1)+0∗s(n−2)+0∗s(n−3)
s ( n − 2 ) = 0 ∗ s ( n − 1 ) + 1 ∗ s ( n − 2 ) + 0 ∗ s ( n − 3 ) s(n-2)=0*s(n-1)+1*s(n-2)+0*s(n-3) s(n−2)=0∗s(n−1)+1∗s(n−2)+0∗s(n−3)
通过一些推导可以得到如下一个矩阵,推导方法见我的博客我们可以得到如下一个矩阵:
[ s ( n ) s ( n + 1 ) s ( n + 2 ) s ( n − 1 ) s ( n ) s ( n + 1 ) s ( n − 2 ) s ( n − 1 ) s ( n ) ] = [ 2 0 − 1 1 0 0 0 1 0 ] n [ s ( 0 ) s ( 1 ) s ( 2 ) s ( 1 ) s ( 0 ) s ( 1 ) s ( − 2 ) s ( − 1 ) s ( 0 ) ] { \left[ \begin{array}{ccc} s(n) & s(n+1) & s(n+2)\\ s(n-1) & s(n) & s(n+1)\\ s(n-2) & s(n-1) & s(n) \end{array} \right ]}={ \left[ \begin{array}{ccc} 2 & 0 & -1\\ 1 & 0 & 0\\ 0 & 1 & 0 \end{array} \right ]}^n{ \left[ \begin{array}{ccc} s(0) & s(1) & s(2)\\ s(1) & s(0) & s(1)\\ s(-2) & s(-1) & s(0) \end{array} \right ]} ⎣⎡s(n)s(n−1)s(n−2)s(n+1)s(n)s(n−1)s(n+2)s(n+1)s(n)⎦⎤=⎣⎡210001−100⎦⎤n⎣⎡s(0)s(1)s(−2)s(1)s(0)s(−1)s(2)s(1)s(0)⎦⎤
然后可以通过 s ( 2 ) = 2 ∗ s ( 1 ) − s ( − 1 ) , s ( 1 ) = 2 ∗ s ( 0 ) − s ( − 2 ) s(2)=2*s(1)-s(-1),s(1)=2*s(0)-s(-2) s(2)=2∗s(1)−s(−1),s(1)=2∗s(0)−s(−2)求出 s ( − 1 ) 和 s ( − 2 ) s(-1)和s(-2) s(−1)和s(−2),虽然这样没有科学依据而正解是通过矩阵的逆,然后通过几个一元一次方程求解,但是我发现其实和这样解出的结果是一样的,那就干脆这样求好了,之前写的几道这样求也是对的
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int Mod=1e9+7;
struct Matrix{
ll matrix[105][105];
};
int n;
Matrix mul(Matrix a,Matrix b){
Matrix ans;
memset(ans.matrix,0,sizeof ans.matrix);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int k=1;k<=n;k++){
ans.matrix[i][j]+=a.matrix[i][k]*b.matrix[k][j]%Mod;
if(ans.matrix[i][j]<0) ans.matrix[i][j]=Mod+ans.matrix[i][j]; //中间结果可能为负数那么需要加上Mod
else ans.matrix[i][j]%=Mod;
}
return ans;
}
Matrix qkp(Matrix mx,ll x){
Matrix ans;
memset(ans.matrix,0,sizeof ans.matrix);
if(x==-1) return ans;
for(int i=1;i<=n;i++) ans.matrix[i][i]=1;
while(x){
if(x&1) ans=mul(ans,mx);
mx=mul(mx,mx);
x>>=1;
}
return ans;
}
int main(){
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int t,l,r,q;
Matrix mx,dw;
n=3;
mx.matrix[1][1]=2,mx.matrix[1][2]=0,mx.matrix[1][3]=-1;
mx.matrix[2][1]=1,mx.matrix[2][2]=0,mx.matrix[2][3]=0;
mx.matrix[3][1]=0,mx.matrix[3][2]=1,mx.matrix[3][3]=0;
dw.matrix[1][1]=0,dw.matrix[1][2]=1,dw.matrix[1][3]=2;
dw.matrix[2][1]=0,dw.matrix[2][2]=0,dw.matrix[2][3]=1;
dw.matrix[3][1]=-1,dw.matrix[3][2]=0,dw.matrix[3][3]=0;
cin>>t;
while(t--){
cin>>l>>r;
Matrix res1=qkp(mx,r),res2=qkp(mx,l-1);
res1=mul(res1,dw),res2=mul(res2,dw);
cout<<(res1.matrix[1][1]-res2.matrix[1][1]+Mod)%Mod<<endl;
}
return 0;
}