传送门

Solution

用线段树维护矩阵

第一个操作相当于区间乘

第二个操作相当于区间求和

Code 

#include<bits/stdc++.h>
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
#define mod 1000000007
#define MN 100005
#define mid ((l+r)>>1)
int n,m;
struct matrix
{
ll a[2][2];
matrix(){memset(a,0,sizeof a);}
matrix operator *(const matrix &b) const
{
register matrix c;register int i,j,k;
for(i=0;i<2;++i)for(j=0;j<2;j++)for(k=0;k<2;++k)
(c.a[i][j]+=b.a[i][k]*a[k][j]%mod)%=mod;
return c;
}
matrix operator +(const matrix &b) const
{
register matrix c;register int i,j;
for(i=0;i<2;++i)for(j=0;j<2;++j) c.a[i][j]=(b.a[i][j]+a[i][j])%mod;
return c;
} }tmp,xxx,t[MN<<2],lazy[MN<<2],orig,pro,unit;
void fpow(int x)
{
for(tmp=unit,xxx=pro;x;x>>=1,xxx=xxx*xxx) if(x&1) tmp=tmp*xxx;
}
void print(matrix x)
{
for(int i=0;i<2;++i)
{
for(int j=0;j<2;++j) printf("%d ",x.a[i][j]);
puts("");
}
puts("");
}
inline void pushdown(int x)
{
t[x<<1]=t[x<<1]*lazy[x];t[x<<1|1]=t[x<<1|1]*lazy[x];
lazy[x<<1]=lazy[x<<1]*lazy[x];lazy[x<<1|1]=lazy[x<<1|1]*lazy[x];
lazy[x]=unit;
}
void build(int x,int l,int r)
{
if(l==r){fpow(read()-1),t[x]=orig*tmp,lazy[x]=unit;return;}
build(x<<1,l,mid);build(x<<1|1,mid+1,r);
t[x]=t[x<<1]+t[x<<1|1];lazy[x]=unit;
}
matrix query(int x,int l,int r,int a,int b)
{
if(a==l&&r==b) return t[x];
pushdown(x);
if(b<=mid) return query(x<<1,l,mid,a,b);
if(a>mid) return query(x<<1|1,mid+1,r,a,b);
return query(x<<1,l,mid,a,mid)+query(x<<1|1,mid+1,r,mid+1,b);
}
void Modify(int x,int l,int r,int a,int b)
{
if(a==l&&b==r){lazy[x]=lazy[x]*tmp,t[x]=t[x]*tmp;return;}
pushdown(x);
if(b<=mid) Modify(x<<1,l,mid,a,b);
else if(a>mid) Modify(x<<1|1,mid+1,r,a,b);
else Modify(x<<1,l,mid,a,mid),Modify(x<<1|1,mid+1,r,mid+1,b);
t[x]=t[x<<1]+t[x<<1|1];
}
int main()
{
unit.a[0][0]=unit.a[1][1]=1;
orig.a[0][0]=1;
pro.a[0][0]=pro.a[0][1]=pro.a[1][0]=1;
n=read(),m=read();
build(1,1,n);
register int type,l,r;
while(m--)
{
type=read();l=read();r=read();
if(type==1) fpow(read()),Modify(1,1,n,l,r);
else printf("%lld\n",query(1,1,n,l,r).a[0][0]);
}
return 0;
}

Blog来自PaperCloud,未经允许,请勿转载,TKS!

最新文章

  1. 通过cmd完成FTP上传文件操作
  2. 计算机网络(1)-----网络层IP协议概述
  3. IOS开发-代码规范
  4. 用SSH指令批量修改文件夹 文件权限和拥有者
  5. spark-DataFrame之RDD和DataFrame之间的转换
  6. Jmeter使用——参数化
  7. 2015美团网 哈工大 第k个排列
  8. JQUERY1.9学习笔记 之基本过滤器(五) 大于选择器
  9. 世界之窗(TheWorld)浏览器 3.6.1.0 简体中文绿色版
  10. 玩转spring boot——结合阿里云持续交付
  11. 1.熟悉Java基本类库系列 - 目录
  12. 谈一谈Java8的函数式编程(二) --Java8中的流
  13. DOM中的事件对象(event)
  14. Nagle算法
  15. Python之celery的简介与使用
  16. [转载]Oracle用户创建及权限设置
  17. [书籍]用UWP复习《C#并发编程经典实例》
  18. BZOJ.3227.[SDOI2008]红黑树tree(树形DP 思路)
  19. Gartner2017年BI研究计划曝光,来看看他研究的都是啥?
  20. 更新本地git仓库的远程地址(remote地址)

热门文章

  1. GC偏好
  2. canvas上画出坐标集合,并标记新坐标,背景支持放大缩小拖动功能
  3. python爬虫 urllib模块url编码处理
  4. iPhone的xib与iPad的xib相互转换
  5. IOS模拟器调试ANE
  6. java23种设计模式专攻:生产者-消费者模式的三种实现方式
  7. 微信公众号&amp;小程序 -- 获取并解密用户数据(获取openId、unionId)
  8. 加密类型、数据加密解密过程以及CA创建
  9. ssmtp脚本发中文邮件的笔记
  10. python解析传入的命令行参数 argv