Description

给定一个数列,维护两种操作

操作 \(1\),将区间 \([l,r]\) 的数字统一加 \(x\)。

操作 \(2\),求 \(\sum \limits_{i=l}^r f(val[i])\),其中 \(f(i)\) 表示斐波那契数列的第 \(i\) 项。‘

答案对 \(10^9+7\) 取模。

Solution

线段树维护矩阵。

因为是斐波那契数列,容易想到用矩阵快速幂来求这个东西。

想这样做的话,要想清楚两个问题:

  1. 因为题目中求的是和,那么知道 \([l,mid]\) 和\([mid+1,r]\) 的答案能否快速合并出 \([l,r]\) 的答案呢?
  2. 如果知道了 \([l,r]\) 的答案,对于区间加 \(x\) 操作,能否快速得知操作后的答案呢?

对于第一个问题,由于矩阵具有分配律,即 \(a\times b+a\times c=a\times(b+c)\),所以对于一段区间的矩阵可以相加维护。

对于第二个问题,显然将 \([l,r]\) 的矩阵乘上转移矩阵的 \(x\) 次方即可。

综上,两个问题想清楚之后,我们用线段树来维护区间中的矩阵。

Code

// By YoungNeal
#include<cstdio>
#include<cctype>
#define N 100005
#define int long long
const int mod=1e9+7; int n,m;
int val[N]; struct Matrix{
int m[4][4]; void clear(){
for(int i=0;i<4;i++){
for(int j=0;j<4;j++)
m[i][j]=0;
}
} void init(){
for(int i=0;i<4;i++)
m[i][i]=1;
} void print(){
for(int i=1;i<=2;i++){
for(int j=1;j<=2;j++)
printf("i=%I64d,j=%I64d,m=%I64d\n",i,j,m[i][j]);
}
} bool empty(){
if(m[1][1]!=1) return 0;
if(m[1][2]!=0) return 0;
if(m[2][1]!=0) return 0;
if(m[2][2]!=1) return 0;
return 1;
} Matrix operator*(const Matrix &y) const {
Matrix z; z.clear();
for(int i=1;i<=2;i++){
for(int k=1;k<=2;k++){
for(int j=1;j<=2;j++)
z.m[i][j]=(z.m[i][j]+m[i][k]*y.m[k][j])%mod;
}
}
return z;
} friend Matrix operator+(Matrix a,Matrix b){
Matrix c;c.clear();
for(int i=1;i<=2;i++){
for(int j=1;j<=2;j++)
c.m[i][j]=(a.m[i][j]+b.m[i][j])%mod;
}
return c;
} }; Matrix dw,fir;
Matrix mat[N<<2],lazy[N<<2]; int getint(){
int x=0;char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return x;
} Matrix ksm(Matrix a,int b){
Matrix ret; ret.clear(); ret.init();
while(b){
if(b&1) ret=ret*a;
a=a*a;
b>>=1;
}
return ret;
} void pushup(int cur){
mat[cur]=mat[cur<<1]+mat[cur<<1|1];
} void build(int cur,int l,int r){
mat[cur].clear();
lazy[cur].clear();
lazy[cur].init();
if(l==r){
mat[cur]=fir*ksm(dw,val[l]-1);
return;
}
int mid=l+r>>1;
build(cur<<1,l,mid);
build(cur<<1|1,mid+1,r);
pushup(cur);
} void pushdown(int cur,int l,int r){
if(lazy[cur].empty()) return;
mat[cur<<1]=mat[cur<<1]*lazy[cur];
lazy[cur<<1]=lazy[cur<<1]*lazy[cur];
mat[cur<<1|1]=mat[cur<<1|1]*lazy[cur];
lazy[cur<<1|1]=lazy[cur<<1|1]*lazy[cur];
lazy[cur].clear();
lazy[cur].init();
} void modify(int cur,int ql,int qr,int l,int r,Matrix x){
if(ql<=l and r<=qr){
mat[cur]=mat[cur]*x;
lazy[cur]=lazy[cur]*x;
return;
}
pushdown(cur,l,r);
int mid=l+r>>1;
if(ql<=mid)
modify(cur<<1,ql,qr,l,mid,x);
if(mid<qr)
modify(cur<<1|1,ql,qr,mid+1,r,x);
pushup(cur);
} Matrix query(int cur,int ql,int qr,int l,int r){
if(ql<=l and r<=qr)
return mat[cur];
pushdown(cur,l,r);
Matrix ret;ret.clear();
int mid=l+r>>1;
if(ql<=mid)
ret=ret+query(cur<<1,ql,qr,l,mid);
if(mid<qr)
ret=ret+query(cur<<1|1,ql,qr,mid+1,r);
return ret;
} signed main(){
dw.clear(); fir.clear();
dw.m[1][1]=1;fir.m[1][1]=1;
dw.m[1][2]=1;fir.m[1][2]=1;
dw.m[2][1]=1;fir.m[2][1]=0;
dw.m[2][2]=0;fir.m[2][2]=0;
n=getint(),m=getint();
for(int i=1;i<=n;i++)
val[i]=getint();
build(1,1,n);
while(m--){
if(getint()==1){
int l=getint(),r=getint(),x=getint();
modify(1,l,r,1,n,ksm(dw,x));
}
else{
int l=getint(),r=getint();
printf("%I64d\n",query(1,l,r,1,n).m[1][2]%mod);
}
}
return 0;
}

最新文章

  1. 关于Karaf Container 4.0.7
  2. [数据分析]excel带名称的四象限散点图制作
  3. IOS Socket 03-建立连接与登录
  4. Spring的循环依赖问题
  5. 分布式PostGIS系列【2】——pgpool-II
  6. C#语言之“string格式的日期时间字符串转为DateTime类型”的方法(转)
  7. 黑马程序员-------.net基础知识一
  8. -_-#【Canvas】
  9. UVA12304 2D Geometry 110 in 1! 计算几何
  10. ORACLE_INSERT
  11. fs模块练习
  12. C# 解析 sln 文件
  13. The type java.lang.Object cannot be resolved. It is indirectly referenced from required .class files
  14. Nginx 配置文件优化
  15. Codeforces Round #445 Div. 1
  16. 修改注册表.exe的文件目录
  17. (一) 天猫精灵接入Home Assistant- hass对接天猫精灵
  18. 网站性能优化小结和spring整合redis
  19. shell 中变获取值及运算的几种方法
  20. jQuery碎语(3) 动画特效

热门文章

  1. playframework链接MySQL数据库的问题
  2. mySQL安装与基础配置
  3. [Machine Learning][The Analytics Edge][Predicting Earnings from Census Data]
  4. 学习Tensorflow的LSTM的RNN例子
  5. form表单保存和取出
  6. HDU 2639 01背包(分解)
  7. [UWP]不那么好用的ContentDialog
  8. 大数据搜索引擎之elasticsearch使用篇(一)
  9. nginx: [emerg] getpwnam(&quot;nginx&quot;) failed
  10. MongoDB 字符串值长度条件查询