用线段树储存价值和,因为矩阵 a1 * b + a2 * b + a3 * b + a4 * b + a5 * b = (a1 + a2 + a3 + a4 + a5) * b;
然后进行下优化,尽量减少快速幂的运算数量
#include
#include
#include
#include
#define lson i<<1
#define rson (i<<1) + 1
#define maxn 100005
#define LL long long
using namespace std;
int n,k,b,m;
LL mod = 1000000007ll;
//快速幂
struct ma{
int m[2][2],row,col;
ma()
{
memset(m,0,sizeof(m));
row = col = 0;
}
ma operator * (ma ma1) //乘
{
ma ans;
ans.row = row;
ans.col = ma1.col;
for(int i = 0;i < ans.row;i++)
for(int j = 0;j < ans.col;j++)
{
for(int k = 0;k < col;k++)
{
ans.m[i][j] = (ans.m[i][j] + ((LL)m[i][k] * ma1.m[k][j])) % mod;
}
}
return ans;
}
ma operator + (ma ma1) //加
{
ma ans;
ans.row = row;
ans.col = col;
for(int i = 0;i < row;i++)
for(int j = 0;j < col;j++)
{
ans.m[i][j] = ma1.m[i][j] + m[i][j];
ans.m[i][j] %= mod;
}
return ans;
}
ma operator^(int n) // 快速幂
{
ma ans,ma1;
ans.row = row; ans.col = col;
for(int i = 0;i < row;i++)
ans.m[i][i] = 1;
ma1.row = row; ma1.col = col;
for(int i = 0;i < row;i++)
for(int j = 0;j < col;j++)
ma1.m[i][j] = m[i][j];
while(n)
{
if(n&1)ans = ans * ma1;
ma1 = ma1 * ma1;
n >>= 1;
}
return ans;
}
}E, mul;
ma va[maxn * 4], add[maxn * 4];
void pushUp(int i)
{
va[i] = va[lson] + va[rson];
}
void pushDown(int i)
{
va[lson] = va[lson] * add[i];
va[rson] = va[rson] * add[i];
add[lson] = add[lson] * add[i];
add[rson] = add[rson] * add[i];
add[i] = E;
}
void build(int i, int l, int r)
{
add[i] = E;
if(l == r)
{
int pre;
scanf("%d", &pre);
pre--;
va[i] = mul ^ pre;
return;
}
int mid = (l + r) / 2;
build(lson , l, mid);
build(rson , mid + 1, r);
pushUp(i);
}
void update(int i, int l, int r, int L , int R, ma ADD)
{
if(l == L && r == R)
{
va[i] = va[i] * ADD;
add[i] = add[i] * ADD;
return;
}
pushDown(i);
int mid = (l + r) / 2;
if(R <= mid) update(lson, l, mid, L, R, ADD);
else if(L > mid) update(rson, mid + 1, r, L, R, ADD);
else{
update(lson, l, mid, L , mid, ADD);
update(rson, mid + 1, r, mid + 1, R, ADD);
}
pushUp(i);
}
int query(int i, int l, int r, int L, int R)
{
if(l == L && r == R)
{
return va[i].m[0][0];
}
pushDown(i);
int mid = (l + r) / 2;
if(R <= mid) return query(lson, l, mid, L , R);
else if(L > mid) return query(rson, mid + 1, r, L, R);
else{
return (query(lson, l, mid, L , mid) + query(rson, mid + 1, r, mid + 1, R))%mod;
}
}
int main()
{
E.row = 2, E.col = 2;
E.m[0][0] = 1, E.m[0][1] = 0;
E.m[1][0] = 0, E.m[1][1] = 1;
mul.row = 2, mul.col = 2;
mul.m[0][0] = 1, mul.m[0][1] = 1;
mul.m[1][0] = 1, mul.m[1][1] = 0;
scanf("%d%d", &n,&m);
build(1, 1, n);
while(m--)
{
int flag;
scanf("%d", &flag);
int a, b, c;
if(flag == 1){
scanf("%d%d%d", &a, &b, &c);
ma ADD = (mul ^ c);
update(1, 1, n, a, b, ADD);
}
else {
scanf("%d%d", &a,&b);
printf("%d\n", query(1, 1, n, a, b));
}
}
return 0;
}