#include <iostream>
using namespace std;
namespace Matr {
const int MX = 105;
const int mod = 1e9 + 7;
struct Matrix {
int a[MX][MX];
int N, M;
void init() {
for(int i = 1; i <= N; i++)
for(int j = 1; j <= M; j++)
a[i][j] = 0;
}
Matrix operator * (const Matrix &t) const {
Matrix res;
res.N = N;
res.M = t.M;
res.init();
for(int k = 1; k <= M; k++) {
for(int i = 1; i <= N; i++) {
for(int j = 1; j <= t.M; j++) {
res.a[i][j] += a[i][k] * t.a[k][j] % mod;
res.a[i][j] %= mod;
}
}
}
return res;
}
bool operator == (const Matrix &t) const {
if(N != t.N || M != t.M) return false;
for(int i = 1; i <= N; i++)
for(int j = 1; j <= M; j++)
if(a[i][j] != t.a[i][j])
return false;
return true;
}
Matrix operator + (const Matrix &t) const {
Matrix res;
res.N = N;
res.M = M;
for(int i = 1; i <= N; i++)
for(int j = 1; j <= M; j++)
res.a[i][j] = a[i][j] + t.a[i][j];
return res;
}
void read(int n, int m) {
N = n;
M = m;
init();
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
cin >> a[i][j];
}
void output() {
for(int i = 1; i <= N; i++) {
for(int j = 1; j <= M; j++)
cout << a[i][j] << ' ';
cout << endl;
}
}
};
Matrix dwjz(int n) {
Matrix tmp;
tmp.init();
tmp.N = n;
tmp.M = n;
for(int i = 1; i <= n; i++)
tmp.a[i][i] = 1;
return tmp;
}
Matrix jzksm(Matrix Ma, int b) {
Matrix res = dwjz(Ma.N);
while(b) {
if(b & 1) res = res * Ma;
Ma = Ma * Ma;
b >>= 1;
}
return res;
}
}
using namespace Matr;
Matrix base, dw, modu;
struct node {
int left, right;
Matrix lazy, sum;
}t[200005];
void update(int id) {
t[id].sum = t[id << 1].sum * t[id << 1].lazy + t[id << 1 | 1].sum + t[id << 1 | 1].lazy;
}
void pushdown(int id) {
if(!(t[id].lazy == dw)) {
t[id << 1].lazy = t[id << 1].lazy * t[id].lazy;
t[id << 1 | 1].lazy = t[id << 1 | 1].lazy * t[id].lazy;
update(id);
t[id].lazy = dw;
}
}
void buildtree(int id, int l, int r) {
t[id].left = l;
t[id].right = r;
t[id].lazy = dw;
if(l == r) {
int tmp;
cin >> tmp;
t[l].sum = modu * jzksm(base, tmp - 2);
return;
}
int mid = (l + r) >> 1;
buildtree(id << 1, l, mid);
buildtree(id << 1 | 1, mid + 1, r);
update(id);
}
void change(int id, int l, int r, int c) {
if(t[id].left == l && t[id].right == r) {
t[id].lazy = t[id].lazy * jzksm(base, c - 1);
return;
}
pushdown(id);
if(r <= t[id << 1].right)
change(id << 1, l, r, c);
else if(t[id << 1 | 1].left <= l)
change(id << 1 | 1, l, r, c);
else {
change(id << 1, l, t[id << 1].right, c);
change(id << 1 | 1, t[id << 1 | 1].left, r, c);
}
update(id);
}
Matrix query(int id, int l, int r) {
if(t[id].left == l && t[id].right == r)
return t[id].sum * t[id].lazy;
pushdown(id);
if(r <= t[id << 1].right)
return query(id << 1, l, r);
else if(t[id << 1 | 1].left <= l)
return query(id << 1 | 1, l, r);
else
return query(id << 1, l, t[id << 1].right) + query(id << 1 | 1, t[id << 1 | 1].left, r);
}
int main() {
modu.N = 1;
modu.M = 2;
modu.a[1][1] = modu.a[1][2] = 1;
base.N = base.M = 2;
base.a[1][1] = base.a[1][2] = base.a[2][1] = 1;
base.a[2][2] = 0;
dw = dwjz(2);
int n, m;
cin >> n >> m;
buildtree(1, 1, n);
while(m--) {
int op;
cin >> op;
if(op == 1) {
int l, r, c;
cin >> l >> r >> c;
change(1, l, r, c);
} else {
int l, r;
cin >> l >> r;
cout << query(1, l, r).a[1][1] << endl;
}
}
return 0;
}
编译不成功。