rt,调破防了
#include<bits/stdc++.h>
#define ll long long
#define int long long
using namespace std;
const int N=1e5+10,mod=1e9+7;
int n,m,a[N];
struct Matrix{
ll a[4][4];
void clear(int x){
memset(a,x,sizeof(a));
}
void init(){// 初始化为对角矩阵
a[0][0]=1;a[0][1]=0;
a[1][0]=0;a[1][1]=1;
}
}T;
Matrix operator +(const Matrix& A,const Matrix& B){
Matrix res;res.clear(0);
for(int i=0;i<=1;i++)
for(int j=0;j<=1;j++) res.a[i][j]=(A.a[i][j]+B.a[i][j])%mod;
return res;
}
Matrix operator *(const Matrix& A,const Matrix& B){
Matrix res;res.clear(0);
for(int i=0;i<=1;i++)
for(int j=0;j<=1;j++)
for(int k=0;k<=1;k++)
res.a[i][j]=(res.a[i][j]+(A.a[i][k]*B.a[k][j])%mod)%mod;
return res;
}
Matrix operator ^(Matrix A,int p){
Matrix res;res.init();
while(p){
if(p&1) res=res*A;
A=A*A;p>>=1;
}
return res;
}
struct Nd{
int l,r;
Matrix sum,add;
}tr[N*2];
void pushup(int u){
tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum;
}
void pushdown(int u){
Nd &lc=tr[u<<1],&rc=tr[u<<1|1];
lc.add=lc.add*tr[u].add; // 相当于 a^(b+c)=(a^b)*(a^c)
rc.add=rc.add*tr[u].add;
lc.sum=lc.sum*tr[u].add;
rc.sum=rc.sum*tr[u].add;
tr[u].add.init();
// 矩阵乘法满足分配律,但是只有在对角矩阵的时候才满足交换律
}
void build(int u,int l,int r){
tr[u]={l,r};
tr[u].add.init();
if(l==r){
if(a[l]==1) tr[u].sum.a[0][0]=1;
else tr[u].sum.a[0][0]=tr[u].sum.a[0][1]=1;
if(a[l]>2) tr[u].sum=tr[u].sum*(T^(a[l]-2));
return;
}
int mid=l+r>>1;
build(u<<1,l,mid);build(u<<1|1,mid+1,r);
pushup(u);
}
void modify(int u,int l,int r,Matrix v){
if(tr[u].l>r||tr[u].r<l) return;
if(tr[u].l>=l&&tr[u].r<=r){
tr[u].add=tr[u].add*v;
tr[u].sum=tr[u].sum*v;
return;
}
pushdown(u);
modify(u<<1,l,r,v);modify(u<<1|1,l,r,v);
pushup(u);
}
int query(int u,int l,int r){
if(tr[u].l>r||tr[u].r<l) return 0;
if(tr[u].l>=l&&tr[u].r<=r) return tr[u].sum.a[0][0];
pushdown(u);
return (query(u<<1,l,r)+query(u<<1|1,l,r))%mod;
}
signed main(){
T.a[0][0]=T.a[0][1]=T.a[1][0]=1;
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
build(1,1,n);
while(m--){
int op,l,r,v;
scanf("%lld%lld%lld",&op,&l,&r);
if(op==1){
scanf("%lld",&v);
modify(1,l,r,T^v);
}
else{
printf("%lld\n",query(1,l,r)%mod);
}
}
return 0;
}