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;
}

转载于:https://www.cnblogs.com/YoungNeal/p/9113761.html

[CF718C] Sasha and Array相关推荐

  1. 【题解】 CF718C Sasha and Array

    \(Description:\) 设计一个数据结构,支持区间加,区间求斐波那契和,比如求\(\sum_{i=l}^{r} f(a_i)\) \(Sample\) \(Input:\) 5 4 1 1 ...

  2. CF719E. Sasha and Array [线段树维护矩阵]

    CF719E. Sasha and Array 题意: 对长度为 n 的数列进行 m 次操作, 操作为: a[l..r] 每一项都加一个常数 C, 其中 0 ≤ C ≤ 10^9 求 F[a[l]]+ ...

  3. 【codeforces 718 CD】C. Sasha and ArrayD. Andrew and Chemistry

    C. Sasha and Array 题目大意&题目链接: http://codeforces.com/problemset/problem/718/C 长度为n的正整数数列,有m次操作,$o ...

  4. [动态dp]线段树维护转移矩阵

    背景:czy上课讲了新知识,从未见到过,总结一下. 所谓动态dp,是在动态规划的基础上,需要维护一些修改操作的算法. 这类题目分为如下三个步骤:(都是对于常系数齐次递推问题) 1先不考虑修改,不考虑区 ...

  5. linux 粘贴内容命令行,Linux下命令行中的复制和粘贴

    PHP面向对象常见的关键字和魔术方法 在PHP5的面向对象程序设计中提供了一些常见的关键字,用来修饰类.成员属性或成员方法,使他们具有特定的功能,例如final.static.const等关键字.还有 ...

  6. c语言定义int 输出4386,C语言 · 矩阵乘法

    问题描述 输入两个矩阵,分别是m*s,s*n大小.输出两个矩阵相乘的结果. 输入格式 第一行,空格隔开的三个正整数m,s,n(均不超过200). 接下来m行,每行s个空格隔开的整数,表示矩阵A(i,j ...

  7. 有趣题目和认知合集(持续更新)

    写写对一些算法的理解,挂几个有意思的题,可能也会挂几个板子题 算法理解偏向于能懂即可,没有严格的证明 快乐几何 [1.2]Volatile Kite 点到直线 快乐搜与暴力 [2.4]Short Co ...

  8. 2016区域赛前冲刺训练

    UPD 2016.10.23 shift-and (2题) Codeforces 训练 现在已经完成了: 191 [Codeforces Round #377] (6/6) Div 2 A Buy a ...

  9. CF刷题(03)——难度2100~2400

    这个博客记录2100到2400共17个题 2100 1.B. Maximum Value 题意:You are given a sequence a consisting of nnn integer ...

最新文章

  1. Learning C# by Developing Games with Unity 5.x(2nd) 学习
  2. 系列:iOS开发-C语言基础
  3. 【Paper】An Experiment Comparing Double Exponential Smoothing and Kalman Filter-Based Predict
  4. 微信小程序开发-入门基础
  5. 并发和Read-copy update(RCU)
  6. ajax请求数据 ztree_ajax 异步获取数据填充到表格显示(ajax) 文档(Options API) DataTables中文网...
  7. 洛谷——P2820 局域网
  8. 笔记:Html.Partial和Html.Action
  9. 转载:Linux内核探索之路——关于书
  10. 十一届恩智浦智能车竞赛 信标 --- 首安666队
  11. [ffmpeg][goav][issues] goav Dictionary crash double free
  12. Oracle minus用法详解及应用实例
  13. FF300R08W2P2B11A 汽车用EasyPACK 模块 2 个独立式
  14. hadoop2.6伪分布+pig0.15+zookeeper3.4.6安装
  15. 跨平台跨端的登录流程及其安全设计
  16. MLY翻译 -- 4.Scale drivers machine learning progress
  17. Could NOT find CUDA (missing: CUDA_INCLUDE_DIRS) (found suitable exact version “11.4“)
  18. 启发式函数在A* 中的作用
  19. 人体姿态识别-pose estimation
  20. 机械学习:二维空间下支持向量机SVM基础学习

热门文章

  1. 《Linux菜鸟入门2》LVM
  2. Android studio 常用快捷键的使用
  3. 淘宝的生态灾难,谁来救赎?
  4. 虚拟化部署之Windows 7中远程管理Hyper-V
  5. 未来的GDI:WPF技术纵览[zz]
  6. 架构师要了解那些??
  7. 小括号教学设计导入_人教版一年级数学下教案 《小括号》教案
  8. python 散点图点击链接图片_在Python和matplotlib中连接三维散点图中的两点
  9. xp系统更改计算机名BIOS设置,XP系统如何设置Netbios名|XP系统设置Netbios名的方法...
  10. javascript读取文本文件到二维数组代码_十行代码说清楚:leetcode 二维数组中的查找...