题目翻译:
有一个长为 \(n\) 的数列 \(a_{1},a_{2}...a_{n}\) ,你需要对这个数列维护如下两种操作:
- \(1\space l \space r\space x\) 表示将数列中的 \(a_{l},a_{l+1}...a_{r-1},a_{r}\) 加上 \(x\)
- \(2\space l\space r\) 表示要你求出 \(\sum_{i=l}^{r}fib(a_{i})\) 对 \(10^9+7\) 取模后的结果
\(fib(x)\) 表示的是斐波那契的第 \(x\) 项, \(fib(1)=1,fib(2)=1,fib(i)=fib(i-1)+fib(i-2)(i>2)\)
显然的线段树维护
我们知道斐波那契数列的某一项可以表示成
\(A\times B^n\) 的形式,\(A,B\) 都是矩阵
那么 \(A\times B^n + A\times C^m=A\times (B^n+C^m)\)
所以就是一个区间乘法修改+区间加法和查询来维护矩阵
// This code writed by chtholly_micromaker(MicroMaker)
#include <bits/stdc++.h>
#define reg register
#define int long long
using namespace std;
const int MaxN=100050;
const int p=1e9+7;
struct Mat
{
int a[2][2];
inline void clear()
{
memset(a,0,sizeof a);
return;
}
inline Mat operator + (const Mat &nt)
{
Mat ans;ans.clear();
for(int i=0;i<2;++i)
for(int j=0;j<2;++j)
ans.a[i][j]=(a[i][j]+nt.a[i][j])%p;
return ans;
}
inline Mat operator += (const Mat &nt)
{
return *this=*this+nt;
}
inline Mat operator * (const Mat &nt)
{
Mat ans;ans.clear();
for(int i=0;i<2;++i)
for(int j=0;j<2;++j)
for(int k=0;k<2;++k)
ans.a[i][j]=(ans.a[i][j]+a[i][k]*nt.a[k][j]%p)%p;
return ans;
}
inline Mat operator *= (const Mat &nt)
{
return *this=*this*nt;
}
inline bool operator != (const Mat &nt) const
{
return a[0][0]!=nt.a[0][0]||a[0][1]!=nt.a[0][1]||
a[1][0]!=nt.a[1][0]||a[1][1]!=nt.a[1][1];
}
}matoption;
Mat val[MaxN<<2],lazy[MaxN<<2];
int a[MaxN];
Mat One={1,0,0,0};
Mat base={1,1,1,0};
Mat Zero={1,0,0,1};
inline Mat fib(Mat a,int b)
{
reg Mat ans;ans=Zero;
for(;b;b>>=1,a*=a)
if(b&1)
ans*=a;
return ans;
}
#define lson (u<<1)
#define rson (u<<1|1)
inline void pushup(int u)
{
val[u]=val[lson]+val[rson];
return;
}
inline void pushdown(int u,int l,int r)
{
if(lazy[u]!=Zero)
{
lazy[lson]*=lazy[u];
lazy[rson]*=lazy[u];
val[lson]*=lazy[u];
val[rson]*=lazy[u];
lazy[u]=Zero;
}
return;
}
inline void buildtr(int u,int l,int r)
{
if(l==r)
{
val[u]=fib(base,a[l]-1);
return;
}
lazy[u]=Zero;
reg int mid=(l+r)>>1;
buildtr(lson,l,mid);
buildtr(rson,mid+1,r);
pushup(u);
return;
}
inline void modify(int u,int l,int r,int ql,int qr,Mat k)
{
if(ql<=l&&r<=qr)
{
lazy[u]*=k;
val[u]*=k;
return;
}
pushdown(u,l,r);
reg int mid=(l+r)>>1;
if(ql<=mid)
modify(lson,l,mid,ql,qr,k);
if(mid<qr)
modify(rson,mid+1,r,ql,qr,k);
pushup(u);
return;
}
inline Mat query(int u,int l,int r,int ql,int qr)
{
if(ql<=l&&r<=qr)
return val[u];
pushdown(u,l,r);
reg int mid=(l+r)>>1;
reg Mat ans;ans.clear();
if(ql<=mid)
ans+=query(lson,l,mid,ql,qr);
if(mid<qr)
ans+=query(rson,mid+1,r,ql,qr);
return ans;
}
template <class t> inline void read(t &s)
{
s=0;
reg int f=1;
reg char c=getchar();
while(!isdigit(c))
{
if(c=='-')
f=-1;
c=getchar();
}
while(isdigit(c))
s=(s<<3)+(s<<1)+(c^48),c=getchar();
s*=f;
return;
}
signed main(void)
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;++i)
read(a[i]);
buildtr(1,1,n);
reg int opt,l,r,x;
for(int i=1;i<=m;++i)
{
read(opt);read(l);read(r);
if(opt==1)
{
read(x);
modify(1,1,n,l,r,fib(base,x));
}
else
printf("%lld\n",(query(1,1,n,l,r)*One).a[0][0]);
}
return 0;
}