C. Sasha and Array                          time limit per test :  5 seconds                      memory limit per test :  256 megabytes

Description

Sasha has an array of integers a1, a2, ..., an. You have to perform m queries. There might be queries of two types:

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。
  1. 1 l r x — increase all integers on the segment from l to r by values x;
  2. 2 l r — find  Codeforces 718C solution 随笔, where f(x) is the x-th Fibonacci number. As this number may be large, you only have to find it modulo 109 + 7.

In this problem we define Fibonacci numbers as follows: f(1) = 1, f(2) = 1, f(x) = f(x - 1) + f(x - 2) for all x > 2.

Sasha is a very talented boy and he managed to perform all queries in five seconds. Will you be able to write the program that performs as well as Sasha?

Input

The first line of the input contains two integers n and m (1 ≤ n ≤ 100 000, 1 ≤ m ≤ 100 000) — the number of elements in the array and the number of queries respectively.

The next line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 109).

Then follow m lines with queries descriptions. Each of them contains integers tpi, li, ri and may be xi (1 ≤ tpi ≤ 2, 1 ≤ li ≤ ri ≤ n, 1 ≤ xi ≤ 109). Here tpi = 1 corresponds to the queries of the first type and tpi corresponds to the queries of the second type.

It's guaranteed that the input will contains at least one query of the second type.

Output

For each query of the second type print the answer modulo 109 + 7.

Example Input
5 4
1 1 2 1 1
2 1 5
1 2 4 2
2 2 4
2 1 5
Example Output
5
7
9
Note

Initially, array a is equal to 1, 1, 2, 1, 1.

The answer for the first query of the second type is f(1) + f(1) + f(2) + f(1) + f(1) = 1 + 1 + 1 + 1 + 1 = 5.

After the query 1 2 4 2 array a is equal to 1, 3, 4, 3, 1.

The answer for the second query of the second type is f(3) + f(4) + f(3) = 2 + 3 + 2 = 7.

The answer for the third query of the second type is f(1) + f(3) + f(4) + f(3) + f(1) = 1 + 2 + 3 + 2 + 1 = 9.

没什么可说的,就是线段树维护fib递推矩阵,线段树不难写,难写的是矩阵部分,细节很多。要是封装性太强容易把代码写得很java。

  1 /* basic header */
  2 #include <iostream>
  3 #include <cstdio>
  4 #include <cstdlib>
  5 #include <string>
  6 #include <cstring>
  7 #include <cmath>
  8 #include <cstdint>
  9 #include <climits>
 10 #include <float.h>
 11 /* STL */
 12 #include <vector>
 13 #include <set>
 14 #include <map>
 15 #include <queue>
 16 #include <stack>
 17 #include <algorithm>
 18 #include <array>
 19 #include <iterator>
 20 /* define */
 21 #define ll long long
 22 #define dou double
 23 #define pb emplace_back
 24 #define mp make_pair
 25 #define fir first
 26 #define sec second
 27 #define sot(a,b) sort(a+1,a+1+b)
 28 #define rep1(i,a,b) for(int i=a;i<=b;++i)
 29 #define rep0(i,a,b) for(int i=a;i<b;++i)
 30 #define repa(i,a) for(auto &i:a)
 31 #define eps 1e-8
 32 #define int_inf 0x3f3f3f3f
 33 #define ll_inf 0x7f7f7f7f7f7f7f7f
 34 #define lson curPos<<1
 35 #define rson curPos<<1|1
 36 /* namespace */
 37 using namespace std;
 38 /* header end */
 39 
 40 const int maxn = 1e5 + 10;
 41 const int mod = 1e9 + 7;
 42 
 43 struct Matrix
 44 {
 45     ll data[2][2];
 46     Matrix()
 47     {
 48         data[0][0] = data[0][1] = data[1][0] = data[1][1] = 0;
 49     }
 50     //变为转移矩阵
 51     inline void tran()
 52     {
 53         data[0][1] = data[1][0] = data[1][1] = 1, data[0][0] = 0;
 54     }
 55     //初始化为对角矩阵
 56     inline void init()
 57     {
 58         *this = Matrix();
 59         rep1(i, 0, 1) data[i][i] = 1;
 60     }
 61     //返回矩阵第x行
 62     inline ll *operator[](int x)
 63     {
 64         return data[x];
 65     }
 66     //定义矩阵乘法
 67     inline void operator*=(Matrix &rhs)
 68     {
 69         Matrix qAns;
 70         rep1(k, 0, 1)
 71         {
 72             rep1(i, 0, 1)
 73             {
 74                 rep1(j, 0, 1)
 75                 qAns[j][i] = (qAns[j][i] + data[j][k] * rhs[k][i]) % mod;
 76             }
 77         }
 78         *this = qAns;
 79     }
 80     //矩阵快速幂
 81     inline void operator^=(int x)
 82     {
 83         Matrix base = *this, qAns;
 84         rep1(i, 0, 1) qAns[i][i] = 1;
 85         for (register int i = x; i; i >>= 1, base *= base)
 86             if (i & 1) qAns *= base;
 87         *this = qAns;
 88     }
 89     inline void operator+=(Matrix &rhs)
 90     {
 91         rep1(i, 0, 1)
 92         {
 93             rep1(j, 0, 1)
 94             {
 95                 data[i][j] = (data[i][j] + rhs[i][j]) % mod;
 96             }
 97         }
 98     }
 99     //输出
100     inline void pr()
101     {
102         rep1(t, 0, 1)
103         {
104             rep1(i, 0, 1) printf("%d ", data[t][i]);
105             puts("");
106         }
107     }
108 } seg[maxn << 2], add[maxn << 2];
109 
110 int n, m;
111 Matrix qAns, markdown;
112 bool lazyTag[maxn << 2];
113 
114 inline void pushdown(int curPos)
115 {
116     if (!lazyTag[curPos]) return;
117     seg[lson] *= add[curPos]; seg[rson] *= add[curPos];
118     add[lson] *= add[curPos]; add[rson] *= add[curPos];
119     lazyTag[lson] = lazyTag[rson] = 1;
120     add[curPos].init(); lazyTag[curPos] = 0;
121 }
122 
123 void build(int curPos, int curL, int curR)
124 {
125     if (curL == curR)
126     {
127         seg[curPos].tran();
128         add[curPos].init();
129         int tmp; scanf("%d", &tmp);
130         seg[curPos] ^= tmp - 1;
131         return;
132     }
133     int mid = (curL + curR) >> 1;
134     add[curPos].init();
135     build(lson, curL, mid); build(rson, mid + 1, curR);
136     seg[curPos] = Matrix();
137     seg[curPos] += seg[lson]; seg[curPos] += seg[rson];
138 }
139 
140 void update(int curPos, int curL, int curR, int qL, int qR)
141 {
142     if (qL <= curL && curR <= qR)
143     {
144         add[curPos] *= markdown; seg[curPos] *= markdown; lazyTag[curPos] = 1;
145         return;
146     }
147     int mid = (curL + curR) >> 1;
148     pushdown(curPos);
149     if (qL <= mid) update(lson, curL, mid, qL, qR);
150     if (mid < qR) update(rson, mid + 1, curR, qL, qR);
151     seg[curPos] = Matrix();
152     seg[curPos] += seg[lson]; seg[curPos] += seg[rson];
153 }
154 
155 void query(int curPos, int curL, int curR, int qL, int qR)
156 {
157     if (qL <= curL && curR <= qR)
158     {
159         qAns += seg[curPos];
160         return;
161     }
162     int mid = (curL + curR) >> 1;
163     pushdown(curPos);
164     if (qL <= mid) query(lson, curL, mid, qL, qR);
165     if (mid < qR) query(rson, mid + 1, curR, qL, qR);
166     seg[curPos] = Matrix();
167     seg[curPos] += seg[lson]; seg[curPos] += seg[rson];
168 }
169 
170 int main()
171 {
172     scanf("%d%d", &n, &m);
173     build(1, 1, n);
174     rep1(cnt, 1, m)
175     {
176         int op; scanf("%d", &op);
177         if (op == 1)
178         {
179             int x, y, t; scanf("%d%d%d", &x, &y, &t);
180             markdown.tran(); markdown ^= t;
181             update(1, 1, n, x, y);
182         }
183         else
184         {
185             int x, y; scanf("%d%d", &x, &y);
186             qAns = Matrix();
187             query(1, 1, n, x, y);
188             printf("%lld\n", (qAns[0][0] + qAns[0][1]) % mod);
189         }
190     }
191     return 0;
192 }

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄