通过题目给的递推公式 可以的出其矩阵形式 然后就是求某一区间的矩阵乘积 线段树或者rmq都可以解
也可以只维护一个前缀积 然后求矩阵的逆
#include <bits/stdc++.h> using namespace std; #define ll long long #define M 1000000007 struct node { int l; int r; ll mat[2][2]; }; node tree[400010]; ll res[2][2]; ll num[100010]; int n; void mul(ll a[][2],ll b[][2],ll c[][2]) { ll t[2][2]; int i,j,k; for(i=0;i<2;i++) { for(j=0;j<2;j++) { t[i][j]=0; for(k=0;k<2;k++) { t[i][j]=(t[i][j]+(a[i][k]*b[k][j])%M)%M; } } } memcpy(c,t,sizeof(t)); return; } void pushup(int cur) { mul(tree[2*cur].mat,tree[2*cur+1].mat,tree[cur].mat); return; } void build(int l,int r,int cur) { int m; tree[cur].l=l; tree[cur].r=r; if(l==r) { tree[cur].mat[0][0]=0,tree[cur].mat[0][1]=num[l]; tree[cur].mat[1][0]=1,tree[cur].mat[1][1]=1; return; } m=(l+r)/2; build(l,m,2*cur); build(m+1,r,2*cur+1); pushup(cur); return; } void query(int pl,int pr,int cur) { if(pl<=tree[cur].l&&tree[cur].r<=pr) { mul(res,tree[cur].mat,res); return; } if(pl<=tree[2*cur].r) query(pl,pr,2*cur); if(pr>=tree[2*cur+1].l) query(pl,pr,2*cur+1); return; } int main() { ll ans; int t,q,i,l,r; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&q); for(i=1;i<=n;i++) { scanf("%lld",&num[i]); } build(1,n,1); while(q--) { scanf("%d%d",&l,&r); if(r-l==0) { printf("%lld\n",num[l]%M); } else if(r-l==1) { printf("%lld\n",num[r]%M); } else { res[0][0]=1,res[0][1]=0; res[1][0]=0,res[1][1]=1; query(l+2,r,1); ans=((num[l]*res[0][1])%M+(num[l+1]*res[1][1])%M)%M; printf("%lld\n",ans); } } } return 0; }