Sasha has an array of integers a1, a2, ..., an. You have to perform m queries. There might be queries of two types:
- 1 l r x — increase all integers on the segment from l to r by values x;
- 2 l r — find , 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?
输入
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 tpicorresponds to the queries of the second type.
It's guaranteed that the input will contains at least one query of the second type.
输出
For each query of the second type print the answer modulo 109 + 7.
样例
Input
5 4
1 1 2 1 1
2 1 5
1 2 4 2
2 2 4
2 1 5
Output
5
7
9
注意
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.
------------------------------------------------------------
题目大意:两个操作 1 l r x(从l到r上的值+x)2 l r(斐波那契求和)
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const ll mod=1e9+7;
ll a[maxn];
struct node
{
ll a[2][2];
};
node add(node A,node B)//矩阵相加
{
node C;
for(int i=0; i<2; i++)
{
for(int j=0; j<2; j++)
{
C.a[i][j]=A.a[i][j]+B.a[i][j];
if(C.a[i][j]>=mod)C.a[i][j]-=mod;
}
}
return C;
}
node mul(node A,node B)//矩阵相乘
{
node C = {0};
for(int i=0; i<2; i++)
{
for(int j=0; j<2; j++)
{
for(int k=0; k<2; k++)
{
C.a[i][j] = (C.a[i][j] + (A.a[i][k]*B.a[k][j]))%mod;
}
}
}
return C;
}
node pow_mod(ll x)//矩阵快速幂
{
node s;
node y;
s.a[0][0]=s.a[1][1]=1;//单位矩阵
s.a[0][1]=s.a[1][0]=0;
y.a[0][0]=y.a[0][1]=y.a[1][0]=1;//转换矩阵
y.a[1][1]=0;
while(x)
{
if(x&1)s=mul(s,y);
y=mul(y,y);
x>>=1;
}
return s;
}
struct Tree
{
int l,r,mark;
node sum,fs;
} tr[4*maxn];
inline void pushup(int o)//更新节点
{
tr[o].sum=add(tr[2*o].sum,tr[2*o+1].sum);//矩阵相加
}
inline void pushdown(int o)
{
if(tr[o].mark)
{
tr[o].mark=0;
tr[2*o].mark=1;
tr[2*o+1].mark=1;
tr[2*o].sum=mul(tr[2*o].sum,tr[o].fs);
tr[2*o+1].sum=mul(tr[2*o+1].sum,tr[o].fs);
tr[2*o].fs=mul(tr[2*o].fs,tr[o].fs);
tr[2*o+1].fs=mul(tr[2*o+1].fs,tr[o].fs);
tr[o].fs.a[0][0]=tr[o].fs.a[1][1]=1;
tr[o].fs.a[1][0]=tr[o].fs.a[0][1]=0;
}
}
void build(int o,int L,int R)
{
tr[o].l=L;
tr[o].r=R;
tr[o].mark=0;
tr[o].fs.a[0][0]=tr[o].fs.a[1][1]=1;//单位矩阵
tr[o].fs.a[0][1]=tr[o].fs.a[1][0]=0;
if(L>=R)
{
tr[o].sum=pow_mod(a[L]);//节点存矩阵的快速幂
return ;
}
int mid=(L+R)/2;
build(2*o,L,mid);
build(2*o+1,mid+1,R);
pushup(o);
}
ll query(int o,int L,int R)//各节点斐波那契数值加和
{
if(L<=tr[o].l&&R>=tr[o].r)
{
return tr[o].sum.a[0][0];
}
int mid=(tr[o].l+tr[o].r)/2;
pushdown(o);
ll ans=0;
if(L<=mid)ans+=query(2*o,L,R);
if(R>mid)ans+=query(2*o+1,L,R);
pushup(o);
return ans%mod;
}
void update(int o,int L,int R,node num)//区间更新
{
if(L<=tr[o].l&&R>=tr[o].r)
{
tr[o].fs=mul(tr[o].fs,num);
tr[o].mark=1;
tr[o].sum=mul(tr[o].sum,num);
return ;
}
pushdown(o);
int mid=(tr[o].l+tr[o].r)/2;
if(L<=mid)update(2*o,L,R,num);
if(R>mid)update(2*o+1,L,R,num);
pushup(o);
}
int n,m;
int main()
{
scanf("%d %d",&n,&m);
for(int i=1; i<=n; i++)
{
scanf("%lld",&a[i]);
a[i]--;//次数应为-1次
}
build(1,1,n);
int op,u,v;
ll temp;
while(m--)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d %d %lld",&u,&v,&temp);
node num=pow_mod(temp);//转换矩阵的t-1次方
update(1,u,v,num);
}
else
{
scanf("%d %d",&u,&v);
printf("%lld\n",query(1,u,v));
}
}
return 0;
}