之前板刷了很多的矩阵的题目。结果心中就有了一个很错误的想法。
就是矩阵的题目都是用来高次幂运算的。
今天看了这道题目,一开始感觉是矩阵,后来看看了,感觉不是矩阵,就放弃了。
后来放学的时候,SCF跟我说这道题目是线段树+矩阵。
我就又开始想了这道题目。
后来仔细想了想发现,原来是线段树预处理矩阵,然后每次询问O(log(n))。
又学到了一招,真棒
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
using namespace std;
#define LL long long
#define MOD 1000000007
struct matrix
{LL mat[3][3];
}A[110000],B;
struct list
{matrix a;int l;int r;
}node[110000*4];
matrix mul(matrix a,matrix b)
{matrix c;int i,j,k;for(i=1;i<=2;i++){for(j=1;j<=2;j++){c.mat[i][j]=0;for(k=1;k<=2;k++){c.mat[i][j]+=a.mat[i][k]*b.mat[k][j];}c.mat[i][j]=c.mat[i][j]%MOD;}}return c;
}
matrix build(int l,int r,int st)
{if(l==r){node[st].l=l;node[st].r=r;node[st].a=A[l];return node[st].a;}matrix a,b;int mid=(l+r)/2;a=build(l,mid,st*2);b=build(mid+1,r,st*2+1);node[st].l=l;node[st].r=r;node[st].a=mul(b,a);return node[st].a;
}
matrix ans(int x,int y,int st)
{int l=node[st].l;int r=node[st].r;if(x<=l&&r<=y){return node[st].a;}if(x>r||y<l){matrix a;a.mat[1][1]=1;a.mat[1][2]=0;a.mat[2][2]=1;a.mat[2][1]=0;return a;}int mid=(l+r)/2;if(y<=mid)return ans(x,y,st*2);else if(x>mid)return ans(x,y,st*2+1);else{return mul(ans(x,y,st*2+1),ans(x,y,st*2));}
}
void qus(int x,int y)
{if(x==y||x==y-1){cout<<A[y].mat[1][2]<<endl;return;}matrix C;B.mat[1][1]=A[x+1].mat[1][2];B.mat[1][2]=0;B.mat[2][1]=A[x].mat[1][2];B.mat[2][2]=0;C=ans(x+2,y,1);C=mul(C,B);cout<<C.mat[1][1]<<endl;
}
int main()
{int T,x,n,m,i,y;scanf("%d",&T);while(T--){scanf("%d%d",&n,&m);for(i=1;i<=n;i++){scanf("%d",&x);A[i].mat[1][1]=1;A[i].mat[1][2]=x;A[i].mat[2][1]=1;A[i].mat[2][2]=0;}build(1,n,1);while(m--){scanf("%d%d",&x,&y);qus(x,y);}}return 0;
}