566人阅读 评论(0)

# [Codeforces 719 E. Sasha and Array] 矩阵快速幂+线段树

AlB+Al+1B++ArB=(Al+Al+1++Ar)B

#include <bits/stdc++.h>
using namespace std;

#define FIN             freopen("input.txt","r",stdin)
#define FOUT            freopen("output.txt","w",stdout)
#define lson            l, mid, (rt << 1)
#define rson            mid + 1, r, (rt << 1 | 1)
#define __mid__         int mid = (l + r) >> 1

typedef __int64 LL;

const int MAXN = 100000 + 5;
const int MOD = 1e9 + 7;

int N, M, tp, L, R, X;

struct Mat {
static const int MX = 2;
int v[MX][MX];
void O() {
memset(v, 0, sizeof(v));
}
void E() {
O();
for(int i = 0; i < MX; i++) v[i][i] = 1;
}
Mat operator + (const Mat& e) const {
Mat ret; ret.O();
for(int i = 0; i < MX; i++) {
for(int j = 0; j < MX; j++) {
ret.v[i][j] = ((LL)v[i][j] + e.v[i][j]) % MOD;
}
}
return ret;
}
Mat operator - (const Mat& e) const {
Mat ret; ret.O();
for(int i = 0; i < MX; i++) {
for(int j = 0; j < MX; j++) {
ret.v[i][j] = ((LL)v[i][j] - e.v[i][j] + MOD) % MOD;
}
}
return ret;
}
Mat operator * (const Mat& e) const {
Mat ret; ret.O();
for(int k = 0; k < MX; k++) {
for(int i = 0; i < MX; i++) {
if(v[i][k] == 0) continue;
for(int j = 0; j < MX; j++) {
ret.v[i][j] = (ret.v[i][j] + (LL) v[i][k] * e.v[k][j]) % MOD;
}
}
}
return ret;
}
Mat operator ^ (int b) const {
Mat a, ret; ret.E();
memcpy(a.v, v, sizeof(v));
while(b > 0) {
if(b & 1) ret = ret * a;
a = a * a;
b >>= 1;
}
return ret;
}
} ini, tra, mat;

struct Seg {
Mat sum, tag;
bool col;
} seg[MAXN * 3];
inline void pushUp(int rt) {
seg[rt].sum = seg[rt << 1].sum + seg[rt << 1 | 1].sum;
}
inline void down(int rt, int fa) {
seg[rt].col = seg[fa].col;
seg[rt].sum = seg[fa].tag * seg[rt].sum;
seg[rt].tag = seg[fa].tag * seg[rt].tag;
}
inline void pushDown(int rt) {
if(seg[rt].col) {
down(rt << 1, rt);
down(rt << 1 | 1, rt);
seg[rt].tag.E();
seg[rt].col = false;
}
}
void build(int l, int r, int rt) {
seg[rt].tag.E();
seg[rt].col = false;
if(l == r)  {
scanf("%d", &X);
mat = tra ^ (X - 1);
seg[rt].sum = mat * ini;
return;
}
__mid__;
build(lson);
build(rson);
pushUp(rt);
}
void update(int l, int r, int rt) {
if(L <= l && r <= R) {
seg[rt].sum = mat * seg[rt].sum;
seg[rt].tag = mat * seg[rt].tag;
seg[rt].col = true;
return;
}
__mid__;
pushDown(rt);
if(L <= mid) update(lson);
if(R > mid) update(rson);
pushUp(rt);
}
int query(int l, int r, int rt) {
if(L <= l && r <= R) {
return seg[rt].sum.v[0][0];
}
__mid__;
pushDown(rt);
int ret = 0;
if(L <= mid) ret = query(lson);
if(R > mid) ret += query(rson);
return ret % MOD;
}

int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif // ONLINE_JUDGE
ini.v[0][0] = 1, ini.v[0][1] = 0;
ini.v[1][0] = 0, ini.v[1][1] = 0;
tra.v[0][0] = 1, tra.v[0][1] = 1;
tra.v[1][0] = 1, tra.v[1][1] = 0;
scanf("%d %d", &N, &M);
build(1, N, 1);
while(M --) {
scanf("%d %d %d", &tp, &L, &R);
if(tp == 1) {
scanf("%d", &X);
mat = tra ^ X;  /// 因为把这个写在update里面，TLE了好几发...
update(1, N, 1);
} else {
printf("%d\n", query(1, N, 1));
}
}
return 0;
}

2
0

* 以上用户言论只代表其个人观点，不代表CSDN网站的观点或立场
个人资料
• 访问：294867次
• 积分：5763
• 等级：
• 排名：第5246名
• 原创：273篇
• 转载：8篇
• 译文：0篇
• 评论：44条
友情链接
最新评论