题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5235
题意:
题意很好懂 就是
给定一个数列 a1,a2,...,an
对于一个递推式 F[L]=a[L],F[L+1]=a[L+1],F[X] = F[X-1]+F[X-2]*aX,
然后给定m个询问,每次给定L,R, 求F(R);
对于这个递推式 每一项我们可以得到一个状态转移矩阵
| F[x] | | 1 , a[x] |
| |= | |
| F[x-1] | | 1 , 0 |
所以我们可以用线段树维护这个矩阵,值得因为矩阵的乘法满足结合律不满足交换律
因此我们在维护的时候需要注意一下 F[R] = (Mr*Mr-1*.....*Ml+2)*A;要注意维护的时候
要保证好这个顺序。
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define PB push_back
#define MP make_pair
#define REP(i,n) for(int i=0;i<(n);++i)
#define FOR(i,l,h) for(int i=(l);i<=(h);++i)
#define DWN(i,h,l) for(int i=(h);i>=(l);--i)
#define IFOR(i,h,l,v) for(int i=(h);i<=(l);i+=(v))
#define CLR(vis) memset(vis,0,sizeof(vis))
#define MST(vis,pos) memset(vis,pos,sizeof(vis))
#define MAX3(a,b,c) max(a,max(b,c))
#define MAX4(a,b,c,d) max(max(a,b),max(c,d))
#define MIN3(a,b,c) min(a,min(b,c))
#define MIN4(a,b,c,d) min(min(a,b),min(c,d))
#define PI acos(-1.0)
#define INF 1000000000
#define LINF 1000000000000000000LL
#define eps 1e-8
#define LL long long
#define lson(id) id<<1
#define rson(id) id<<1|1
using namespace std;
const LL mod = 1e9+7;
const int maxn = 1e5+10;
int a[maxn];
struct matrix{
LL m[2][2];
matrix(){CLR(m);}
matrix operator *(const struct matrix &tmp){
matrix ans;
REP(i,2){
REP(j,2){
ans.m[i][j]=0;
REP(k,2)
ans.m[i][j]=(ans.m[i][j]+m[i][k]*tmp.m[k][j])%mod;
}
}
return ans;
}
};
struct seg_tree{
int l,r;
matrix ans;
}t[maxn<<2];
void build(int id,int l,int r){
t[id].l=l,t[id].r=r;
if(l==r){
t[id].ans.m[0][0]=1;
t[id].ans.m[0][1]=a[l];
t[id].ans.m[1][0]=1;
t[id].ans.m[1][1]=0;
//cout<<"*** "<<t[id].ans.m[0][1]<<endl;
return;
}
int mid=(l+r)>>1;
build(lson(id),l,mid);
build(rson(id),mid+1,r);
t[id].ans=t[rson(id)].ans*t[lson(id)].ans;
}
matrix query(int id,int l,int r){
if(l==t[id].l&&r==t[id].r) return t[id].ans;
int mid = (t[id].l+t[id].r)>>1;
if(mid>=r) return query(lson(id),l,r);
else if(mid<l) return query(rson(id),l,r);
else return query(rson(id),mid+1,r)*query(lson(id),l,mid);
}
int main()
{
int t,n,m,l,r;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
FOR(i,1,n) scanf("%d",&a[i]);
build(1,1,n);
REP(i,m){
scanf("%d%d",&l,&r);
if(r-l>=2){
matrix tmp;
tmp.m[0][0]=a[l+1];
tmp.m[1][0]=a[l];
matrix ans =query(1,l+2,r)*tmp;
printf("%lld\n",ans.m[0][0]);
}
else
printf("%d\n",a[r]);
}
}
return 0;
}