C. Sasha and Array

time limit per test:5 seconds
memory limit per test:256 megabytes
input:standard input
output:

standard output

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 modulo109 + 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 tpiliri 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.

Examples

input
5 4
1 1 2 1 1
2 1 5
1 2 4 2
2 2 4
2 1 5

output

5
7
9

Note

Initially, array a is equal to 1, 1, 2, 1, 1.

The answer for the first query of the second type is f(1) + f(1) + f(2) + f(1) + f(1) = 1 + 1 + 1 + 1 + 1 = 5.

After the query 1 2 4 2 array a is equal to 1, 3, 4, 3, 1.

The answer for the second query of the second type is f(3) + f(4) + f(3) = 2 + 3 + 2 = 7.

The answer for the third query of the second type is f(1) + f(3) + f(4) + f(3) + f(1) = 1 + 2 + 3 + 2 + 1 = 9.

Solution

题目大意:维护一个序列,支持两种操作:

1.区间[l,r]的权值+x

2.询问区间[l,r]的函数和,即$\sum _{x=l}^{r}fib(x)$这里的函数即斐波那契函数

一般求斐波那契函数的方法可以考虑矩阵乘法,这里也是这样的。

我们不用线段树维护权值,我们用线段树维护矩阵$fib^{a[l]-1}$。

矩阵的合并是可以相加的。

然后就可以了。

这道题很卡常数,我平常的习惯,矩阵是从1~n,而我这里要是从1开始就TLE了..所以应该从0~n-1

Code

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define LL long long
inline int read()
{
int x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
#define P 1000000007
#define MAXN 100010
int N,M,a[MAXN];
struct MatrixNode{LL a[][]; MatrixNode() {memset(a,,sizeof(a));}}fib;
MatrixNode operator + (MatrixNode x,MatrixNode y)
{
MatrixNode re;
for (int i=; i<=; i++)
for (int j=; j<=; j++)
re.a[i][j]=(x.a[i][j]+y.a[i][j])%P;
return re;
}
MatrixNode operator * (MatrixNode x,MatrixNode y)
{
MatrixNode re;
for (int k=; k<=; k++)
for (int i=; i<=; i++)
if (x.a[i][k])
for (int j=; j<=; j++)
if (y.a[k][j])
(re.a[i][j]+=(x.a[i][k]*y.a[k][j])%P)%=P;
return re;
}
MatrixNode operator ^ (MatrixNode x,int y)
{
MatrixNode re;
for (int i=; i<=; i++) re.a[i][i]=;
for (int i=y; i; i>>=,x=x*x) if (i&) re=re*x;
return re;
}
namespace SegmentTree
{
struct SegmentTreeNode{int l,r; MatrixNode tag,sum;}tree[MAXN<<];
#define ls now<<1
#define rs now<<1|1
inline void Update(int now) {tree[now].sum=tree[ls].sum+tree[rs].sum;}
inline void PushDown(int now)
{
if (tree[now].l==tree[now].r) return;
MatrixNode D=tree[now].tag;
tree[ls].sum=tree[ls].sum*D; tree[ls].tag=tree[ls].tag*D;
tree[rs].sum=tree[rs].sum*D; tree[rs].tag=tree[rs].tag*D;
memset(tree[now].tag.a,,sizeof(tree[now].tag.a));
for (int i=; i<=; i++) tree[now].tag.a[i][i]=;
}
inline void BuildTree(int now,int l,int r)
{
tree[now].l=l; tree[now].r=r;
for (int i=; i<=; i++) tree[now].tag.a[i][i]=;
if (l==r) {tree[now].sum=fib^(a[l]-); return;}
int mid=(l+r)>>;
BuildTree(ls,l,mid); BuildTree(rs,mid+,r);
Update(now);
}
inline void Modify(int now,int L,int R,MatrixNode D)
{
int l=tree[now].l,r=tree[now].r;
PushDown(now);
if (L<=l && R>=r) {tree[now].tag=tree[now].tag*D; tree[now].sum=tree[now].sum*D; return;}
int mid=(l+r)>>;
if (L<=mid) Modify(ls,L,R,D);
if (R>mid) Modify(rs,L,R,D);
Update(now);
}
inline MatrixNode Query(int now,int L,int R)
{
int l=tree[now].l,r=tree[now].r;
PushDown(now);
if (L<=l && R>=r) return tree[now].sum;
int mid=(l+r)>>; MatrixNode re;
if (L<=mid) re=re+Query(ls,L,R);
if (R>mid) re=re+Query(rs,L,R);
return re;
}
}
int main()
{
N=read(),M=read();
for (int i=; i<=N; i++) a[i]=read();
fib.a[][]=; fib.a[][]=; fib.a[][]=; fib.a[][]=;
SegmentTree::BuildTree(,,N);
while (M--)
{
int opt=read(),x,y,z;
switch (opt)
{
case : x=read(),y=read(),z=read(); SegmentTree::Modify(,x,y,fib^z); break;
case : x=read(),y=read(); printf("%I64d\n",SegmentTree::Query(,x,y).a[][]%P); break;
}
}
return ;
}

【Codeforces718C】Sasha and Array 线段树 + 矩阵乘法的更多相关文章

  1. CF718C Sasha and Array 线段树 + 矩阵乘法

    有两个操作: 将 $[l,r]$所有数 + $x$ 求 $\sum_{i=l}^{r}fib(i)$ $n=m=10^5$   直接求不好求,改成矩阵乘法的形式:  $a_{i}=M^x\times ...

  2. CF718C Sasha and Array 线段树+矩阵加速

    正解:线段树 解题报告: 传送门! 首先这种斐波拉契,又到了1e9的范围,又是求和什么的,自然而然要想到矩阵加速昂 然后这里主要是考虑修改操作,ai+=x如果放到矩阵加速中是什么意思呢QAQ? 那不就 ...

  3. CF718C Sasha and Array [线段树+矩阵]

    我们考虑线性代数上面的矩阵知识 啊呸,是基础数学 斐波那契的矩阵就不讲了 定义矩阵 \(f_x\) 是第 \(x\) 项的斐波那契矩阵 因为 \(f_i * f_j = f_{i+j}\) 然后又因为 ...

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

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

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

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

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

  7. hdu 5068(线段树+矩阵乘法)

    矩阵乘法来进行所有路径的运算, 线段树来查询修改. 关键还是矩阵乘法的结合律. Harry And Math Teacher Time Limit: 5000/3000 MS (Java/Others ...

  8. 【对不同形式矩阵的总结】WC 2009 最短路径问题(线段树+矩阵乘法)

    题意 ​ 题目链接:https://www.luogu.org/problem/P4150 ​ 一个 \(6\times n\) 的网格图,每个格点有一个初始权值.有两种操作: 修改一个格子的权值 求 ...

  9. MAZE(2019年牛客多校第二场E题+线段树+矩阵乘法)

    题目链接 传送门 题意 在一张\(n\times m\)的矩阵里面,你每次可以往左右和下三个方向移动(不能回到上一次所在的格子),\(1\)表示这个位置是墙,\(0\)为空地. 现在有\(q\)次操作 ...

随机推荐

  1. SqlServer数据类型

    Character 字符串: 数据类型 描述 存储 char(n) 固定长度的字符串.最多 8,000 个字符. n varchar(n) 可变长度的字符串.最多 8,000 个字符.   varch ...

  2. 迁移Reporting Services的方法与WMI错误

    今天上午,接到一个任务:迁移SQL SERVER 2005的报表服务到另外一台SQL SERVER 2008服务器,结果等我备份了两边服务器的ReportServer,ReportServerTemp ...

  3. HTML5【语法要点】

    一.头部设置 <!--页面窗口自动调整到设备宽度,并禁止用户及缩放页面--> <meta name="viewport" content="width= ...

  4. .dat 导入sqlserver2000

    所有任务->还原数据库->从设备.选项中改变路径地址

  5. FFmpeg编译找不到库文件

    在编译FFmpeg的时候,用./configure 进行配置,经常会出现找不到库文件的情况,原因大概就两个: 1.没有安装库文件或者安装的库文件版本不对 2.FFmpeg没有找到库文件 前者的问题好解 ...

  6. android xml 布局错误

    最近重新安装了下android开发环境,发现在调整页面的时候 ,老是报以下错误,导致无法静态显示ui效果. Missing styles. Is the correct theme chosen fo ...

  7. java反射 cglib asm相关资料

    有篇文章对java反射的调用的效率做了测试,写的比较好.猛击下面地址 http://www.blogjava.net/stone2083/archive/2010/09/15/332065.html ...

  8. 强制浏览器使用兼容模式,Web.config,httpProtocol

    对于一些政府类的网站,很多支持IE6~8,而不支持使用更高版本浏览器浏览.虽然有些浏览器会自动使用兼容模式,或有些人会手动调整浏览器的兼容模式,但不是每一个人.每一款浏览器都可以做到用兼容模式.所以, ...

  9. MySql错误代码1045的解决方案

    错误代码 1045Access denied for user 'root'@'localhost' (using password:YES) 解决办法是重新设置root用户密码,在Windows平台 ...

  10. java Socket编程-基于TCP

    package com.wzy.Test; import java.io.BufferedReader; import java.io.IOException; import java.io.Inpu ...