传送门

题目

Sasha has an array of integers a1, a2, ..., an. You have to perform m queries. There might be queries of two types:

  1. 1 l r x — increase all integers on the segment from l to r by values x;
  2. 2 l r — find , where f(x) is the x-th Fibonacci number. As this number may be large, you only have to find it modulo 109 + 7.

In this problem we define Fibonacci numbers as follows: f(1) = 1, f(2) = 1, f(x) = f(x - 1) + f(x - 2) for all x > 2.

Sasha is a very talented boy and he managed to perform all queries in five seconds. Will you be able to write the program that performs as well as Sasha?

Input

The first line of the input contains two integers n and m (1 ≤ n ≤ 100 000, 1 ≤ m ≤ 100 000) — the number of elements in the array and the number of queries respectively.

The next line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 109).

Then follow m lines with queries descriptions. Each of them contains integers tpi, li, ri and may be xi (1 ≤ tpi ≤ 2, 1 ≤ li ≤ ri ≤ n, 1 ≤ xi ≤ 109). Here tpi = 1 corresponds to the queries of the first type and tpi corresponds to the queries of the second type.

It's guaranteed that the input will contains at least one query of the second type.

Output

For each query of the second type print the answer modulo 109 + 7.

题目大意

给你一个长度为n的数列an,有两种操作

1、将L到R的ai加上X

2、询问L到R之间,f(aL)+f(aL+1)+……+f(aR)的和

f是斐波那契函数

分析

我们可以将斐波那契数转化成它所对应的矩阵,对于每一次加x就是给原来矩阵乘上斐波那契矩阵的x次方。将为赋值的矩阵全部初始化为单位矩阵,然后进行朴素的线段树为何两节点之和即可。

代码

#pragma G++ optimize (2)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
#define rri register int
const int mod=1e9+;
struct mat {
int g[][];
};
mat d[],one,per;
mat add[];
inline mat operator * (const mat a,const mat b){
mat c;
c.g[][]=c.g[][]=c.g[][]=c.g[][]=;
for(rri i=;i<=;++i)
for(rri k=;k<=;++k)
for(rri j=;j<=;++j)
c.g[i][j]=(c.g[i][j]+(long long)a.g[i][k]*b.g[k][j]%mod)%mod;
return c;
}
inline mat operator + (const mat a,const mat b){
mat c;
for(rri i=;i<=;++i)
for(rri j=;j<=;++j)
c.g[i][j]=(a.g[i][j]+b.g[i][j])%mod;
return c;
}
inline mat pw(mat a,int p){
mat res=a;
p-=;
while(p){
if(p&)res=res*a;
a=a*a;
p>>=;
}
return res;
}
inline int read(){
int x=,f=;char s=getchar();
while(s<''||s>''){if(s=='-')f=-;s=getchar();}
while(s>=''&&s<=''){x=(x<<)+(x<<)+(s-'');s=getchar();}
return f*x;
}
inline void build(int le,int ri,int pl,mat k,int wh){
add[wh]=per;
if(le==ri){
d[wh]=k;
return;
}
int mid=(le+ri)>>;
if(mid>=pl)build(le,mid,pl,k,wh<<);
else build(mid+,ri,pl,k,wh<<|);
d[wh]=d[wh<<]+d[wh<<|];
}
inline void pd(int wh){
if(add[wh].g[][]!=||add[wh].g[][]!=||
add[wh].g[][]!=||add[wh].g[][]!=){
add[wh<<]=add[wh<<]*add[wh];
add[wh<<|]=add[wh<<|]*add[wh];
d[wh<<]=d[wh<<]*add[wh];
d[wh<<|]=d[wh<<|]*add[wh];
add[wh]=per;
}
}
inline void update(int le,int ri,int x,int y,mat k,int wh){
if(le>=x&&ri<=y){
add[wh]=add[wh]*k;
d[wh]=d[wh]*k;
return;
}
int mid=(le+ri)>>;
pd(wh);
if(mid>=x)update(le,mid,x,y,k,wh<<);
if(mid<y)update(mid+,ri,x,y,k,wh<<|);
d[wh]=d[wh<<]+d[wh<<|];
}
inline int q(int le,int ri,int x,int y,int wh){
if(le>=x&&ri<=y)return d[wh].g[][]%mod;
int mid=(le+ri)>>,ans=;
pd(wh);
if(mid>=x)ans=(ans+q(le,mid,x,y,wh<<))%mod;
if(mid<y)ans=(ans+q(mid+,ri,x,y,wh<<|))%mod;
d[wh]=d[wh<<]+d[wh<<|];
return ans%mod;
}
int main()
{ int n,m,x,l,r,k;
one.g[][]=,one.g[][]=one.g[][]=one.g[][]=;
per.g[][]=per.g[][]=,per.g[][]=per.g[][]=;
n=read(),m=read();
for(rri i=;i<=n;++i){
x=read();
build(,n,i,pw(one,x),);
}
for(rri i=;i<=m;++i){
k=read();
if(k==){
l=read(),r=read(),x=read();
update(,n,l,r,pw(one,x),);
}else {
l=read(),r=read();
printf("%d\n",q(,n,l,r,)%mod);
}
}
return ;
}

718C Sasha and Array的更多相关文章

  1. CodeForces 718C Sasha and Array

    线段树. 线段树维护区间矩阵和,操作都是最简单的线段树.$lazy$标记不要记录乘了几次,直接记录乘了几次之后的矩阵就可以了,不然每次下传的时候再算一遍时间复杂度会提高. #pragma commen ...

  2. Codeforces 718C. Sasha and Array(线段树)

    传送门 解题思路: 这道题给了我们一个崭新的角度来看线段树. 我们常常使用的线段树是维护区间的函数的. 这里呢,提示我们线段树其实还可以维护递推. 美好的矩阵递推性质支持了这一功能. 或者说,对于递推 ...

  3. [CF 718C] Sasha and Array

    传送门 Solution 用线段树维护矩阵 第一个操作相当于区间乘 第二个操作相当于区间求和 Code  #include<bits/stdc++.h> #define ll long l ...

  4. 【Codeforces718C】Sasha and Array 线段树 + 矩阵乘法

    C. Sasha and Array time limit per test:5 seconds memory limit per test:256 megabytes input:standard ...

  5. codeforces 719E E. Sasha and Array(线段树)

    题目链接: E. Sasha and Array time limit per test 5 seconds memory limit per test 256 megabytes input sta ...

  6. Sasha and Array

    Sasha and Array time limit per test 5 seconds memory limit per test 256 megabytes input standard inp ...

  7. 【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 ...

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

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

  9. Codeforces Round #373 (Div. 2) E. Sasha and Array 线段树维护矩阵

    E. Sasha and Array 题目连接: http://codeforces.com/contest/719/problem/E Description Sasha has an array ...

随机推荐

  1. Python安装升级步骤

    1)安装Pyhton2.7wget http://www.python.org/ftp/python/2.7.5/Python-2.7.5.tar.bz2tar xjvf Python-2.7.5.t ...

  2. C#多线程操作

    static void Main(string[] args) { Thread thread = Thread.CurrentThread; thread.Name = "Main Thr ...

  3. InnoDB引擎的特点及优化方法

    1.什么是InnoDB引擎?      InnoDB引擎是MySQL数据库的另一个重要的存储引擎,正成为目前MySQL AB所发行的新版的标准,被包含在所有二进制安装包里,和其他存储引擎相比,Inno ...

  4. C++中声明和定义的区别

    声明 这有一个与这个名字相关的东西,并且它是这个类型的,告诉编译器我要使用它,并期待它定义在某一个地方. 定义 定义是指提供所有必要的信息(占用内存大小),使其能够创建整个实体. 我们必须明白的: 一 ...

  5. Chrome MarkDown Preview Plus

    /************************************************************************** * Chrome MarkDown Previe ...

  6. 自定义Django Command

    转: django的command命令是要放在一个app的management/commands目录下.python2环境中,请确保management和management/commands目录内都 ...

  7. set/multiset容器

    一.二叉树基本概念 二叉树就是任何节点最多只允许有两个子节点.分别是左子节点和右子节点. 二叉搜索树,是指二叉树中的节点按照一定的规则进行排序,使得对二叉树中元素访问更加高效.二叉搜索树的放置规则是: ...

  8. BZOJ2342:[SHOI2011]双倍回文

    浅谈\(Manacher\):https://www.cnblogs.com/AKMer/p/10431603.html 题目传送门:https://www.lydsy.com/JudgeOnline ...

  9. 表有外键所以delete报错了,这里有2种办法处理:

    表有外键所以delete报错了,这里有2种办法处理: (1)      临时设置外键失效 (2)      删除表涉及到的外键的表的数据 2.外键失效的处理方案 mysql> SET FOREI ...

  10. PHP5之前的构造函数与PHP5之后的构造函数的区别

    在PHP5以前的版本中,构造函数的名称必须与类名相同,这种方法在PHP5中仍然可以使用,但现在已经很少有人用了. PHP5以及之后的版本,构造函数用__construct()方法来声明,这样做的好处是 ...