[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 ...
随机推荐
- ES6最新语法
ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准.因为当前版本的ES6是在2015年发布的,所以又称ECMAScript 2015. 也就是说,ES6就是ES2015. ...
- Python3实战系列之九(获取印度售后数据项目)
项目现状:已经部署在服务器上并正常运行了. 1.服务器上的部署 2.下载到服务器的文件列表 3.转存在到数据库SQL Server中的数据 项目总结:这次项目采用python来实现,刚开始还是有点担忧 ...
- 使用PreparedStatement向数据表中插入、修改、删除、获取Blob类型的数据
使用PreparedStatement向数据表中插入.修改.删除.获取Blob类型的数据 2014-09-07 20:17 Blob介绍 BLOB类型的字段用于存储二进制数据 MySQL中,BLOB是 ...
- python闭包和延迟绑定
一.什么是闭包: 1.函数内定义函数. 2.外函数的返回时内函数的引用. 3.内函数使用外函数的局部变量(至少一个). 1 def outfunc(): 2 for num in range(4): ...
- STM32外设初始化步骤
1.定义外设结构体: 2.开启外设时钟: 3.调用缺省值配置函数: 4.外设具体配置: 5.外设使能.
- 第三周Access的总结
一.问;这节课你学到了什么知识? 答:这周我学得比较少,主要是学Access的数据库进行基本的维护. 2.3数据库的基本维护 对Access定期检查,修复是整个数据库重要部分: 1.Access可修复 ...
- Batch Normalization--介绍
思考 YJango的前馈神经网络--代码LV3的数据预处理中提到过:在数据预处理阶段,数据会被标准化(减掉平均值.除以标准差),以降低不同样本间的差异性,使建模变得相对简单. 我们又知道神经网络中的每 ...
- 如何减少SQL Server中的PREEMPTIVE_OS_WRITEFILEGATHER等待类型
在数据库大小分配期间,我正在等待类型PREEMPTIVE_OS_WRITEFILEGATHER.昨天,我将数据库大小配置为供应商建议的值.我们需要将数据库大小设置为700GB,保留150 GB的日志文 ...
- 11.翻译系列:在EF 6中配置一对零或者一对一的关系【EF 6 Code-First系列】
原文链接:https://www.entityframeworktutorial.net/code-first/configure-one-to-one-relationship-in-code-fi ...
- kernel解析dtb为节点
title: 解析dtb为节点 date: 2019/4/26 14:02:18 toc: true --- kernel解析dtb为节点 head.s入口传递 回顾 看以前的笔记 kernel(二) ...