题意:长度为n(n<=100000)的数列,有两种操作(其中F(ai)为fibonacci数列):
1.询问[l,r] 之间f(ai)的和;
2.[l,r]之间的ai均增加v 。
题解:区间操作用到线段树,线段树维护矩阵。f(ai)的计算用到矩阵乘法,f(ai+v)即为两矩阵相乘
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
using namespace std;
typedef long long LL;
const int Maxd=2;
const int M=1000000007;
const int N=100000+10;
struct Matrix{
int a[Maxd][Maxd];
Matrix(int diag=0){
for (int i=0;i<Maxd;i++)
for (int j=0;j<Maxd;j++)
a[i][j]=(i==j)*diag;
}
Matrix operator +(const Matrix&d)const{
Matrix c;
for (int i=0;i<Maxd;i++)
for (int j=0;j<Maxd;j++)
c.a[i][j]=(a[i][j]+d.a[i][j])%M;
return c;
}
Matrix operator *(const Matrix&d)const{
Matrix c;c=Matrix();
for (int k=0;k<Maxd;k++)
for (int i=0;i<Maxd;i++)
for (int j=0;j<Maxd;j++)
c.a[i][j]=(c.a[i][j]+(LL)a[i][k]*d.a[k][j])%M;
return c;
}
bool One(){
for (int i=0;i<Maxd;i++)
for (int j=0;j<Maxd;j++)
if ((i==j && a[i][j]!=1) || (i!=j && a[i][j]!=0))return false;
return true;
}
};
struct Tree{
Matrix Tag,Sum;
}T[N<<2];
int n,m;
Matrix a[N];
Matrix RP(Matrix a,int b){
Matrix c;c=Matrix(1);
for (;b;b>>=1){
if (b&1)c=c*a;
a=a*a;
}
return c;
}
void Build(int p,int L,int R)
{
T[p].Tag=Matrix(1);
if (L==R){
T[p].Sum=a[L];
return ;
}
int mid=(L+R)>>1;
Build(p+p,L,mid);
Build(p+p+1,mid+1,R);
T[p].Sum=T[p+p].Sum+T[p+p+1].Sum;
}
void Push_down(int p,int L,int R)
{
if (!T[p].Tag.One()){
T[p+p].Sum=T[p+p].Sum*T[p].Tag;
T[p+p+1].Sum=T[p+p+1].Sum*T[p].Tag;
T[p+p].Tag=T[p+p].Tag*T[p].Tag;
T[p+p+1].Tag=T[p+p+1].Tag*T[p].Tag;
T[p].Tag=Matrix(1);
}
}
//Sum,Tag
void Insert(int p,int L,int R,int l,int r,Matrix c)
{
if (L==l && R==r) {
T[p].Tag=T[p].Tag*c;
T[p].Sum=T[p].Sum*c;
return ;
}
Push_down(p,L,R);
int mid=(L+R)>>1;
if (r<=mid)Insert(p+p,L,mid,l,r,c);
else if (mid< l)Insert(p+p+1,mid+1,R,l,r,c);
else {
Insert(p+p,L,mid,l,mid,c);
Insert(p+p+1,mid+1,R,mid+1,r,c);
}
T[p].Sum=T[p+p].Sum+T[p+p+1].Sum;//Push_up(p,L,R);
}
int Query(int p,int L,int R,int l,int r)
{
if (L==l && R==r) {
return T[p].Sum.a[0][0];
}
Push_down(p,L,R);
int mid=(L+R)>>1;
int Ret=0;
if (r<=mid)Ret=Query(p+p,L,mid,l,r);
else if (mid< l)Ret=Query(p+p+1,mid+1,R,l,r);
else {
Ret=Query(p+p,L,mid,l,mid)+Query(p+p+1,mid+1,R,mid+1,r);
}
T[p].Sum=T[p+p].Sum+T[p+p+1].Sum;//Push_up(p,L,R);
return Ret%M;
}
int main()
{
//freopen("1.txt","r",stdin);
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++){
int x;scanf("%d",&x);
a[i].a[0][0]=1;a[i].a[0][1]=1;
a[i].a[1][0]=1;a[i].a[1][1]=0;
a[i]=RP(a[i],x-1);//x-1£¬´ïµ½f(x)
}
Build(1,1,n);
while (m--){
int tp,l,r,x;
scanf("%d%d%d",&tp,&l,&r);
if (tp==2){
printf("%d\n",Query(1,1,n,l,r));
}else {
scanf("%d",&x);
Matrix c;
c.a[0][0]=1;c.a[0][1]=1;
c.a[1][0]=1;c.a[1][1]=0;
Insert(1,1,n,l,r,RP(c,x));//x,f(ai + x)
}
}
return 0;
}