题目链接: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; }