CF 316E3 Summer Homework(斐波那契矩阵+线段树)
题目链接:http://codeforces.com/problemset/problem/316/E3
题意:一个数列A三种操作:(1)1 x y将x位置的数字修改为y;(2)2 x y求[x,y]区间的数字的和,和函数为如下;(3)3 x y z将[x,y]区间的数字统一加z。
思路:很明显,这是一个线段树的题目。其中第一种和第三种操作都很容易搞定,第一种直接更新到底;第三种增加标记。显然为了求和,我们必须要在节点上增加一个和,表示以这个节点为根的子树的数字的和函数,这里我们用a来表示。那么,到这里有两件事情要解决:
(1)如何在区间增加一个值x时更新a?设该区间为[L,R],则增加的和为:
(2)已知两段数字的和函数,如何拼接成一个和函数?设前一段为3,后一段为4,那么我们要将后一段修改,修改前为:
修改后为:
为了方便,我们先看看怎么把(1,1,2,3)变为(1,2,3,5),也就是:
其实就是:
我们用a表示某段内(设这一段有x个数)x个数的和函数,b表示后x-1个数的和函数,那么上面其实就是a+b,得到A,那么B怎么得到呢?(AB和ab对应,我们发现B=a),因此我们得到转移矩阵:
注意这个的b和B是为了方便计算我们要新加到线段树节点中的值。那么上面(1,1,2,3)到(3,5,8,13)的转变岂不是成了:
到这里,我们就解决了两段和函数拼成一段的方法。
struct Matrix
{
i64 a[2][2];
void init(int x)
{
clr(a,0);
if(x==1) a[0][0]=a[1][1]=1;
else if(x==2) a[0][0]=a[0][1]=a[1][0]=1;
}
Matrix operator*(Matrix p)
{
Matrix ans;
ans.init(0);
int i,j,k;
FOR0(k,2) FOR0(i,2) FOR0(j,2)
{
ans.a[i][j]+=a[i][k]*p.a[k][j];
ans.a[i][j]%=mod;
}
return ans;
}
};
Matrix A[N];
i64 f[N];
void init()
{
A[0].init(1);
A[1].init(2);
int i;
for(i=2;i<N;i++) A[i]=A[i-1]*A[1];
f[0]=f[1]=1;
for(i=2;i<N;i++) f[i]=(f[i-1]+f[i-2])%mod;
for(i=1;i<N;i++) f[i]=(f[i]+f[i-1])%mod;
}
struct node
{
int L,R;
i64 a,b,flag;
node(){}
node(i64 _a,i64 _b)
{
a=_a;
b=_b;
}
node det(int t)
{
i64 x=(a*A[t].a[0][0]+b*A[t].a[0][1])%mod;
i64 y=(a*A[t].a[1][0]+b*A[t].a[1][1])%mod;
return node(x,y);
}
void add(i64 x)
{
flag=(flag+x)%mod;
a=(a+f[R-L]*x)%mod;
if(R>L) b=(b+f[R-L-1]*x)%mod;
}
node operator+(node p)
{
i64 x=(a+p.a)%mod,y=(b+p.b)%mod;
return node(x,y);
}
};
node a[N<<2];
int b[N];
void pushUp(int t)
{
if(a[t].L==a[t].R) return;
int mid=(a[t].L+a[t].R)>>1;
node temp=a[t*2+1].det(mid-a[t].L+1);
a[t].a=(a[t*2].a+temp.a)%mod;
a[t].b=(a[t*2].b+temp.b)%mod;
}
void pushDown(int t)
{
if(a[t].L==a[t].R) return;
if(a[t].flag)
{
a[t*2].add(a[t].flag);
a[t*2+1].add(a[t].flag);
a[t].flag=0;
}
}
void build(int t,int L,int R)
{
a[t].L=L;
a[t].R=R;
a[t].flag=a[t].b=0;
if(L==R)
{
a[t].a=b[L];
return;
}
int mid=(a[t].L+a[t].R)>>1;
build(t*2,L,mid);
build(t*2+1,mid+1,R);
pushUp(t);
}
void change(int t,int pos,int x)
{
if(a[t].L==a[t].R)
{
a[t].a=x;
a[t].b=0;
a[t].flag=0;
return;
}
pushDown(t);
int mid=(a[t].L+a[t].R)>>1;
if(pos<=mid) change(t*2,pos,x);
else change(t*2+1,pos,x);
pushUp(t);
}
void change(int t,int L,int R,int x)
{
if(a[t].L==L&&a[t].R==R)
{
a[t].add(x);
return;
}
pushDown(t);
int mid=(a[t].L+a[t].R)>>1;
if(R<=mid) change(t*2,L,R,x);
else if(L>mid) change(t*2+1,L,R,x);
else
{
change(t*2,L,mid,x);
change(t*2+1,mid+1,R,x);
}
pushUp(t);
}
node query(int t,int L,int R)
{
if(a[t].L==L&&a[t].R==R) return a[t];
pushDown(t);
node A,B;
int mid=(a[t].L+a[t].R)>>1;
if(R<=mid) A=query(t*2,L,R);
else if(L>mid) A=query(t*2+1,L,R);
else
{
A=query(t*2,L,mid);
B=query(t*2+1,mid+1,R);
A=A+B.det(mid-L+1);
}
pushDown(t);
return A;
}
int n,m;
int main()
{
init();
Rush(n)
{
RD(m);
int i;
FOR1(i,n) RD(b[i]);
build(1,1,n);
int op,x,y,z;
while(m--)
{
RD(op);
if(op==1)
{
RD(x,y);
change(1,x,y);
}
else if(op==2)
{
RD(x,y);
PR(query(1,x,y).a);
}
else
{
RD(x,y,z);
change(1,x,y,z);
}
}
}
}
CF 316E3 Summer Homework(斐波那契矩阵+线段树)的更多相关文章
- Codeforces 446C - DZY Loves Fibonacci Numbers(斐波那契数列+线段树)
Codeforces 题目传送门 & 洛谷题目传送门 你可能会疑惑我为什么要写 *2400 的题的题解 首先一个很明显的想法是,看到斐波那契数列和 \(10^9+9\) 就想到通项公式,\(F ...
- HDU 2855 斐波那契+矩阵快速幂
http://acm.hdu.edu.cn/showproblem.php?pid=2855 化简这个公式,多写出几组就会发现规律 d[n]=F[2*n] 后面的任务就是矩阵快速幂拍一个斐波那契模板出 ...
- 「GXOI / GZOI2019」逼死强迫症——斐波那契+矩阵快速幂
题目 [题目描述] ITX351 要铺一条 $2 \times N$ 的路,为此他购买了 $N$ 块 $2 \times 1$ 的方砖.可是其中一块砖在运送的过程中从中间裂开了,变成了两块 $1 \t ...
- 2018年湘潭大学程序设计竞赛G又见斐波那契(矩阵快速幂)
题意 题目链接 Sol 直接矩阵快速幂 推出来的矩阵应该长这样 \begin{equation*}\begin{bmatrix}1&1&1&1&1&1\\1 & ...
- 以计算斐波那契数列为例说说动态规划算法(Dynamic Programming Algorithm Overlapping subproblems Optimal substructure Memoization Tabulation)
动态规划(Dynamic Programming)是求解决策过程(decision process)最优化的数学方法.它的名字和动态没有关系,是Richard Bellman为了唬人而取的. 动态规划 ...
- 矩阵乘法&&矩阵快速幂&&最基本的矩阵模型——斐波那契数列
矩阵,一个神奇又令人崩溃的东西,常常用来优化序列递推 在百度百科中,矩阵的定义: 在数学中,矩阵(Matrix)是一个按照长方阵列排列的复数或实数集合 ,最早来自于方程组的系数及常数所构成的方阵.这一 ...
- [Codeforces 316E3]Summer Homework(线段树+斐波那契数列)
[Codeforces 316E3]Summer Homework(线段树+斐波那契数列) 顺便安利一下这个博客,给了我很大启发(https://gaisaiyuno.github.io/) 题面 有 ...
- codeforces316E3 Summer Homework(线段树,斐波那契数列)
题目大意 给定一个n个数的数列,m个操作,有三种操作: \(1\ x\ v\) 将\(a_x\)的值修改成v $2\ l\ r\ $ 求 \(\sum_{i=l}^r x_i*f_{i-l}\) 其中 ...
- OptimalSolution(1)--递归和动态规划(1)斐波那契系列问题的递归和动态规划
一.斐波那契数列 斐波那契数列就是:当n=0时,F(n)=0:当n=1时,F(n)=1:当n>1时,F(n) = F(n-1)+F(n-2). 根据斐波那契数列的定义,斐波那契数列为(从n=1开 ...
随机推荐
- threading.Condition()
threading — Thread-based parallelism — Python 3.7.2 documentation https://docs.python.org/3/library/ ...
- ios-多语言版本开发(三)(转载)
写在前面 iOS 多语言版本的开发(二)中我们实现了如何让用户自己去切换系统语言的功能,我们还写了Demo 以供辅助学习:但是,继以上两篇文章都是建立在项目刚刚启动或启动不久,项目中存在的中文字符串 ...
- linux elasticsearch-5.1.1的安装
(一)下载elasticsearch linux安装包 https://www.elastic.co/downloads/past-releases,然后解压,然后要有对应的java8,即必须先安装j ...
- __getattr__,settr
__getattr__ 如果属性查找在实例以及对应的类中(通过__dict__)失败, 那么会调用到类的__getattr__函数, 如果没有定义这个函数,那么抛出AttributeError异常. ...
- mysql python pymysql模块 增删改查 查询 fetchmany fetchall函数
查询的fetchmany fetchall函数 import pymysql mysql_host = '192.168.0.106' port = 3306 mysql_user = 'root' ...
- Python一键安装全部依赖包
requirements.txt用来记录项目所有的依赖包和版本号,只需要一个简单的pip命令就能完成. pip freeze >requirements.txt 然后就可以用 pip insta ...
- 微信小程序性能测试之jmeter踩坑秘籍(前言)
最近要做个微信小程序的性能压测,虽然之前只做过web端的,但想一想都是压后端的接口,所以果断答应了下来,之前对jmeter都是小打小闹,所以趁着这次机会好好摆弄摆弄. ---------------- ...
- c#实现图片二值化例子(黑白效果)
C#将图片2值化示例代码,原图及二值化后的图片如下: 原图: 二值化后的图像: 实现代码: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 2 ...
- 基于androidstudio3.0的build文件配置问题
最近,在研究APP自动化相关的东西,在搭建环境的时候,遇到的坑以及最后解决的方法,不过目前很多东西了解得还不是很细,暂时先简单的记录一下一.build配置文件 主要分为两种: 1.工程下的build配 ...
- BCB 串口控件的使用 TComm
昨天工作用到了串口通信,MMP的,昨天懵逼了一下午,今天终于整通了,身为菜鸟,大师们是不懂这些心痛的. 进入主题:使用BCB提供的控件TComm编程方便且简单,TComm位于System分类里面. ...