#include <iostream>
#define int long long
using namespace std;
const int mod = 1e9+7;
struct Matrix
{
int m[2][2];
void init()
{
m[0][0] = m[1][1] = 1;
}
bool empty()
{
return m[0][0] == m[1][1]&&m[0][0] == 1&&m[0][1] == m[1][0]&&m[0][1] == 0;
}
};
Matrix basic;
struct Tree
{
Matrix tr;
Matrix lz;
};
Tree tr[400001];
int a[100001];
Matrix operator + (const Matrix& x,const Matrix& y)
{
Matrix ans;
for(int i = 0;i <= 1;i++)
{
for(int j = 0;j <= 1;j++)
{
ans.m[i][j] = (x.m[i][j]+y.m[i][j])%mod;
}
}
return ans;
}
Matrix operator * (const Matrix& x,const Matrix& y)
{
Matrix ans;
for(int i = 0;i <= 1;i++)
{
for(int j = 0;j <= 1;j++)
{
for(int k = 0;k <= 1;k++)
{
ans.m[i][j] += (x.m[i][k]*y.m[k][j])%mod;
ans.m[i][j] %= mod;
}
}
}
return ans;
}
Matrix operator ^ (Matrix x,int y)
{
Matrix ans;
ans.init();
while(y)
{
if(y%2 == 1)
{
ans = ans * x;
}
x = x * x;
y /= 2;
}
return ans;
}
void push_down(int p)
{
if (tr[p].lz.empty() == false)
{
tr[p*2].lz = tr[p*2].lz * tr[p].lz;
tr[p*2+1].lz = tr[p*2+1].lz * tr[p].lz;
tr[p*2].tr = tr[p*2].tr * tr[p].lz;
tr[p*2+1].tr = tr[p*2+1].tr * tr[p].lz;
tr[p].lz.init();
}
}
void build_tree(int l,int r,int p)
{
tr[p].lz.init();
if(l == r)
{
if(a[l] == 1)
{
tr[p].tr.m[0][0] = 1;
}
else
{
tr[p].tr.m[0][0] = tr[p].tr.m[0][1] = 1;
}
if(a[l] > 2)
{
tr[p].tr = tr[p].tr * (basic ^ (a[l]-2));
}
return;
}
int mid = (l+r)/2;
build_tree(l,mid,p*2);
build_tree(mid+1,r,p*2+1);
tr[p].tr = tr[p*2].tr + tr[p*2+1].tr;
}
void add(int l,int r,int s,int t,Matrix x,int p)
{
if(s > r||l > t)
{
return;
}
if(s <= l&&r <= t)
{
tr[p].lz = tr[p].lz * x;
tr[p].tr = tr[p].tr * x;
return;
}
push_down(p);
int mid = (l+r)/2;
if(mid >= s)
{
add(l,mid,s,t,x,p*2);
}
if(mid+1 <= t)
{
add(mid+1,r,s,t,x,p*2+1);
}
tr[p].tr = tr[p*2].tr + tr[p*2+1].tr;
}
int sum(int l,int r,int s,int t,int p)
{
if(s > r||l > t)
{
return 0;
}
if(s <= l&&r <= t)
{
return tr[p].tr.m[0][0];
}
push_down(p);
int mid = (l+r)/2;
int ans = 0;
if(mid >= s)
{
ans += sum(l,mid,s,t,p*2);
ans %= mod;
}
if(mid+1 <= t)
{
ans += sum(mid+1,r,s,t,p*2+1);
ans %= mod;
}
tr[p].tr = tr[p*2].tr + tr[p*2+1].tr;
return ans%mod;
}
signed main()
{
basic.m[0][0] = basic.m[0][1] = basic.m[1][0] = 1;
int n,m;
scanf("%lld %lld",&n,&m);
for(int i = 1;i <= n;i++)
{
scanf("%lld",&a[i]);
}
build_tree(1,n,1);
for(int i = 1;i <= m;i++)
{
int op;
scanf("%lld",&op);
if(op == 1)
{
int l,r,x;
scanf("%lld %lld %lld",&l,&r,&x);
printf("%lld %lld\n%lld %lld\n\n",(basic ^ x).m[0][0],(basic ^ x).m[0][1],(basic ^ x).m[1][0],(basic ^ x).m[1][1]);
add(1,n,l,r,basic ^ x,1);
}
else
{
int l,r;
scanf("%lld %lld",&l,&r);
printf("%lld\n",sum(1,n,l,r,1)%mod);
}
}
return 0;
}
照着第三篇题解写的,不知道那里错了,求助