题意:
求一个区间内的的递推公式的值 递推的区间为[l,r][l,r][l,r], 这样因为递推式和矩阵的性质是相同的, 我们可以考虑使用线段树维护矩阵的相乘 这样复杂度就可以做到O(nlogn)O(nlogn)O(nlogn)]
特别需要注意的事情是
因为这个原因wa了无数次我们在线段树中的成分 一定要遵循矩阵相乘的顺序,因为矩阵我们维护的相乘顺序是从rrr −>->−> lll 的 查询的时候当然也需要这样搞了
#include <bits/stdc++.h>
using namespace std;
#define cpp_io() {ios::sync_with_stdio(false); cin.tie(NULL);}
#define rep(i,a,n) for (int i=a;i<n;i++)
#define repp(i,a,n) for (int i=a;i<=n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define CLR(a,b) memset(a,(b),sizeof(a))
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define ls o<<1
#define rs o<<1|1
typedef long long ll;
typedef vector<int> VI;
const int MAXN = (int)1e5+10;
const int INF = 0x3f3f3f3f;
const int mod = (int)1e9+7;
void F() {
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
}
struct mat {
ll a[2][2];
mat() {
CLR(a, 0);
}
mat(ll x) {
a[0][0] = a[1][0] = 1;
a[1][1]=0; a[0][1] = x;
}
mat operator * (const mat &r)const {
mat res;
rep(i,0,2){
rep(j,0,2){
rep(k,0,2){
res.a[i][j]=(res.a[i][j]+a[i][k]*r.a[k][j])%mod;
}
}
}
return res;
}
};
struct node {
int l,r;
mat x;
}t[MAXN<<2];
ll arr[MAXN<<2];
void build(int l,int r,int o) {
t[o].l=l,t[o].r=r;
if(l==r) {
t[o].x=mat(arr[l]);
return;
}
int mid=(l+r)>>1;
build(l,mid,ls); build(mid+1,r,rs);
t[o].x=t[rs].x*t[ls].x;
}
mat query(int l,int r,int o) {
if(t[o].l>=l&&t[o].r<=r) return t[o].x;
int mid=(t[o].l+t[o].r)>>1;
if(r<=mid) return query(l,r,ls);
else if(l>mid) return query(l,r,rs);
else {
return query(mid+1,r,rs)*query(l,mid,ls);
}
}
int main() {
int T; cin>>T;
while(T--) {
int n,m; scanf("%d%d",&n,&m);
repp(i,1,n) scanf("%lld",&arr[i]);
build(1,n,1);
while(m--) {
int l,r; scanf("%d%d",&l,&r);
if(r==l||r==l+1) {
printf("%lld\n",arr[r]);
}
else {
mat ans=query(l+2,r,1);
printf("%lld\n",(ans.a[0][1]*arr[l]+ans.a[0][0]*arr[l+1])%mod);
}
}
}
return 0;
}