[CF718C] Sasha and Array
Description
给定一个数列,维护两种操作
操作 \(1\),将区间 \([l,r]\) 的数字统一加 \(x\)。
操作 \(2\),求 \(\sum \limits_{i=l}^r f(val[i])\),其中 \(f(i)\) 表示斐波那契数列的第 \(i\) 项。‘
答案对 \(10^9+7\) 取模。
Solution
线段树维护矩阵。
因为是斐波那契数列,容易想到用矩阵快速幂来求这个东西。
想这样做的话,要想清楚两个问题:
- 因为题目中求的是和,那么知道 \([l,mid]\) 和\([mid+1,r]\) 的答案能否快速合并出 \([l,r]\) 的答案呢?
- 如果知道了 \([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;
}
[CF718C] Sasha and Array的更多相关文章
- 【题解】[CF718C Sasha and Array]
[题解]CF718C Sasha and Array 对于我这种喜欢写结构体封装起来的选手这道题真是太对胃了\(hhh\) 一句话题解:直接开一颗线段树的矩阵然后暴力维护还要卡卡常数 我们来把\(2 ...
- CF718C Sasha and Array 线段树+矩阵加速
正解:线段树 解题报告: 传送门! 首先这种斐波拉契,又到了1e9的范围,又是求和什么的,自然而然要想到矩阵加速昂 然后这里主要是考虑修改操作,ai+=x如果放到矩阵加速中是什么意思呢QAQ? 那不就 ...
- CF718C Sasha and Array(线段树维护矩阵)
题解 (不会矩阵加速的先去学矩阵加速) 反正我想不到线段树维护矩阵.我太菜了. 我们在线段树上维护一个区间的斐波那契的列矩阵的和. 然后询问时提取每个符合题意列矩阵的答案项(不是列矩阵存了两项吗,一个 ...
- CF718C Sasha and Array 线段树 + 矩阵乘法
有两个操作: 将 $[l,r]$所有数 + $x$ 求 $\sum_{i=l}^{r}fib(i)$ $n=m=10^5$ 直接求不好求,改成矩阵乘法的形式: $a_{i}=M^x\times ...
- CF718C Sasha and Array [线段树+矩阵]
我们考虑线性代数上面的矩阵知识 啊呸,是基础数学 斐波那契的矩阵就不讲了 定义矩阵 \(f_x\) 是第 \(x\) 项的斐波那契矩阵 因为 \(f_i * f_j = f_{i+j}\) 然后又因为 ...
- 【Codeforces718C】Sasha and Array 线段树 + 矩阵乘法
C. Sasha and Array time limit per test:5 seconds memory limit per test:256 megabytes input:standard ...
- codeforces 719E E. Sasha and Array(线段树)
题目链接: E. Sasha and Array time limit per test 5 seconds memory limit per test 256 megabytes input sta ...
- Sasha and Array
Sasha and Array time limit per test 5 seconds memory limit per test 256 megabytes input standard inp ...
- 【codeforces 718 C&D】C. Sasha and Array&D. Andrew and Chemistry
C. Sasha and Array 题目大意&题目链接: http://codeforces.com/problemset/problem/718/C 长度为n的正整数数列,有m次操作,$o ...
随机推荐
- ssh 配置免密失败
多数情况下,可以登录成功.但是也会出现配置不正确,导致失败的时候. 1.检查authorized_keys文件权限,并设置为700 chmod 700 authorized_keys 2.检查/etc ...
- UML标准建模语言与应用实例
一.基本信息 标题:UML标准建模语言与应用实例 时间:2012 出版源:科技创新导报 领域分类:UML标准建模语言 面向对象 系统分析与设计 二.研究背景 问题定义:UML建模语言用图形来表现典型的 ...
- Canny边缘检测算法的一些改进
传统的Canny边缘检测算法是一种有效而又相对简单的算法,可以得到很好的结果(可以参考上一篇Canny边缘检测算法的实现).但是Canny算法本身也有一些缺陷,可以有改进的地方. 1. Canny边缘 ...
- Servlet 中,out.print()与out.write()的区别
最近刚学习了Ajax,其中有通过$.getJSON的实现方式 由于前后端传递值的时候会通过流的方式进行传递,这就不得不涉及到这方面的知识了 PrintWrite out=response.getWri ...
- yum-内网yum源服务器配置(CentOS6.5)
一.安装apache服务1.安装httpd服务 yum -y install httpd (纯内网用rpm包安装也可以) 2.启动httpd服务 service httpd start 二.挂载完整的 ...
- git 包教包会
# Git全面解析 版本控制工具:VSS.CVS.SVN.Git等,其中Git属于绝对霸主地位. 注意:一般版本控制工具包含两部分 客户端(本地):本地编写内容以及版本记录 服务端(网盘):将内容和版 ...
- Python自动化开发 - Python操作Memcached、Redis、RabbitMQ
Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载. 它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速 ...
- Android网络请求与数据解析,使用Gson和GsonFormat解析复杂Json数据
版权声明:未经博主允许不得转载 一:简介 [达叔有道]软件技术人员,时代作者,从 Android 到全栈之路,我相信你也可以!阅读他的文章,会上瘾!You and me, we are family ...
- 国外青少年最喜爱的聊天 app,竟然是 Google Docs
简评: 这还真不是标题党,Google Docs 的协作中内置了实时聊天的功能,也可以进行 comments,颇有种现代「传纸条」的既视感.其实国内的石墨文档.腾讯文档等协作工具也有类似的效果,本文很 ...
- 使用pipenv隔离不同项目的依赖包
pipenv可以为不同的路径创建python环境和依赖包,结合pyenv可以达到为不同项目使用不同python版本,不同依赖包的目的. pip install pipenv #安装pipenv 使用p ...