传送门:CF 719 E
题解
区间更新
注意这里节点是矩阵, 所以初始化要是E
矩阵结合律 + Fibo
la表示lazy不过这里是矩阵, 所以初始是E, sum是区间的ans矩阵, lazy纯粹的标记
AC code:
/*
adrui's submission
Language : C++
Favorite : Dragon Balls
Lover : yy
Motto : Choose & Quit
Standing in the Hall of Fame
*/
#include<iostream>
#include<cstring>
using namespace std;
#define mid ((l + r) >> 1)
#define ls rt << 1, l, mid
#define rs rt << 1 | 1, mid + 1, r
typedef long long LL;
const int MOD = 1E9 + 7;
const int maxn = 100000 + 5;
int d[maxn];
struct Matrix {//矩阵
LL v[2][2];
void clr() {
memset(v, 0, sizeof(v));
}
void E() {//单位矩阵
clr();
for (int i = 0; i < 2; ++i) v[i][i] = 1;
}
void debug() {
for (int i = 0; i < 2; ++i)
for (int j = 0; j < 2; ++j)
cout << v[i][j] << (j == 1 ? "\n" : " ");
}
Matrix operator * (Matrix b) {
Matrix res;
res.clr();
for (int i = 0; i < 2; ++i)
for (int j = 0; j < 2; ++j)
for (int k = 0; k < 2; ++k)
res.v[i][j] = (res.v[i][j] + v[i][k] * b.v[k][j]) % MOD;
return res;
}
Matrix operator + (Matrix b) {
Matrix res;
//res.clr();
for (int i = 0; i < 2; ++i)
for (int j = 0; j < 2; ++j)
res.v[i][j] = (v[i][j] + b.v[i][j]) % MOD;
return res;
}
Matrix operator ^ (int b) {
Matrix res, a;
res.E();
memcpy(a.v, v, sizeof(v));
while (b) {
if (b & 1) res = res * a;
a = a * a;
b >>= 1;
}
return res;
}
}mat, tmp;
struct node {
int lazy;
Matrix sum, la;
}a[maxn << 2];
void pushUp(int rt) {
a[rt].sum = a[rt << 1].sum + a[rt << 1 | 1].sum;
}
void build(int rt, int l, int r) {
a[rt].la.E();//E
a[rt].lazy = 0;
if (l == r) {
cin >> d[l];
a[rt].sum = mat ^ d[l];
return;
}
build(ls);
build(rs);
pushUp(rt);
}
void down(int s, int f) {
a[s].lazy = a[f].lazy;
a[s].la = a[s].la * a[f].la;
a[s].sum = a[s].sum * a[f].la;
}
void pushDown(int rt) {
if (a[rt].lazy) {
down(rt << 1, rt);
down(rt << 1 | 1, rt);
a[rt].lazy = 0;
a[rt].la.E();//E
}
}
void update(int rt, int l, int r, int L, int R) {
if (L <= l && R >= r) {
a[rt].sum = a[rt].sum * tmp;
a[rt].la = a[rt].la * tmp;
a[rt].lazy = 1;
return;
}
pushDown(rt);
if (L <= mid) update(ls, L, R);
if (R > mid) update(rs, L, R);
pushUp(rt);
}
LL query(int rt, int l, int r, int L, int R) {
if (L <= l && R >= r) return a[rt].sum.v[0][1];
pushDown(rt);
LL res = 0;
if (L <= mid) res += query(ls, L, R);
if (R > mid) res += query(rs, L, R);
return res;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif //
cin.tie(0);
cin.sync_with_stdio(false);
mat.clr();
mat.v[0][1] = mat.v[1][0] = mat.v[1][1] = 1;
//Fibonacci底数矩阵
int n, m, op, l, r, x;
while (cin >> n >> m) {
build(1, 1, n);
while (m--) {
cin >> op >> l >> r;
if (op == 1) {
cin >> x;
tmp = mat ^ x;
update(1, 1, n, l, r);
}
else {
LL ans = query(1, 1, n, l, r);
cout << ans % MOD << endl;
}
}
}
return 0;
}