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

题意:f(x)为斐波那契第x项,1是更新l-r的区间f(i+x),2是求区间和;

思路:线段树维护矩阵,将每个f(x)转化为2*2的矩阵,区间更新为乘法;

    需要一点小优化;

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pi (4*atan(1.0))
const int N=1e5+,M=4e6+,inf=1e9+,mod=1e9+;
struct is
{
ll a[][];
void setnum(ll aa,ll b,ll c,ll d)
{
a[][]=aa;
a[][]=b;
a[][]=c;
a[][]=d;
}
void reset()
{
for(int i=;i<=;i++)
for(int t=;t<=;t++)
a[i][t]=;
}
};
is add(is a,is b)
{
for(int i=; i<=; i++)
for(int t=; t<=; t++)
a.a[i][t]=(a.a[i][t]+b.a[i][t])%mod;
return a;
}
struct tree
{
is lazy;
is a;
}tree[N<<];
is gg;
is juzhenmul(is a,is b,ll mod)
{
int i,t,j;
is ans;
ans.reset();
for(i=;i<=;i++)
for(t=;t<=;t++)
for(j=;j<=;j++)
{
ans.a[i][t]+=(a.a[i][j]*b.a[j][t]);
ans.a[i][t]%=mod;
}
return ans;
}
is quickpow(is a,ll x,ll mod)
{
is ans;
ans.setnum(,,,);
while(x)
{
if(x&) ans=juzhenmul(ans,a,mod);
a=juzhenmul(a,a,mod);
x>>=;
}
return ans;
}
is getans(is base,ll x,ll mod)
{
return quickpow(base,x-,mod);
}
void pushup(int pos)
{
tree[pos].a=add(tree[pos<<|].a,tree[pos<<].a);
}
void pushdown(int pos)
{
if(tree[pos].lazy.a[][]!=||tree[pos].lazy.a[][]!=||tree[pos].lazy.a[][]!=||tree[pos].lazy.a[][]!=)
{
tree[pos<<].lazy=juzhenmul(tree[pos<<].lazy,tree[pos].lazy,mod);
tree[pos<<|].lazy=juzhenmul(tree[pos<<|].lazy,tree[pos].lazy,mod);
tree[pos<<].a=juzhenmul(tree[pos].lazy,tree[pos<<].a,mod);
tree[pos<<|].a=juzhenmul(tree[pos].lazy,tree[pos<<|].a,mod);
tree[pos].lazy.setnum(,,,);
}
}
void buildtree(int l,int r,int pos)
{
tree[pos].lazy.setnum(,,,);
if(l==r)
{
ll x;
scanf("%lld",&x);
tree[pos].a=getans(gg,x,mod);
return;
}
int mid=(l+r)>>;
buildtree(l,mid,pos<<);
buildtree(mid+,r,pos<<|);
pushup(pos);
}
void update(int L,int R,int l,int r,int pos,is c)
{
if(L<=l&&r<=R)
{
tree[pos].lazy=juzhenmul(c,tree[pos].lazy,mod);
tree[pos].a=juzhenmul(c,tree[pos].a,mod);
return;
}
pushdown(pos);
int mid=(l+r)>>;
if(L<=mid)
update(L,R,l,mid,pos<<,c);
if(R>mid)
update(L,R,mid+,r,pos<<|,c);
pushup(pos);
}
ll query(int L,int R,int l,int r,int pos)
{
if(L<=l&&r<=R)
return tree[pos].a.a[][];
pushdown(pos);
int mid=(l+r)>>;
ll ans=;
if(L<=mid)
ans+=query(L,R,l,mid,pos<<);
if(R>mid)
ans+=query(L,R,mid+,r,pos<<|);
return ans%mod;
}
int main()
{
gg.setnum(,,,);
int n,m;
scanf("%d%d",&n,&m);
buildtree(,n,);
while(m--)
{
int flag,l,r;
ll c;
scanf("%d%d%d",&flag,&l,&r);
if(flag==)
{
scanf("%lld",&c);
update(l,r,,n,,getans(gg,c+,mod));
}
else
printf("%lld\n",query(l,r,,n,));
}
return ;
}

Codeforces Round #373 (Div. 2) E. Sasha and Array 矩阵快速幂+线段树的更多相关文章

  1. E. Sasha and Array 矩阵快速幂 + 线段树

    E. Sasha and Array 这个题目没有特别难,需要自己仔细想想,一开始我想了一个方法,不对,而且还很复杂,然后lj提示了我一下说矩阵乘,然后再仔细想想就知道怎么写了. 这个就是直接把矩阵放 ...

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

  3. Codeforces Round #257 (Div. 2) B. Jzzhu and Sequences (矩阵快速幂)

    题目链接:http://codeforces.com/problemset/problem/450/B 题意很好懂,矩阵快速幂模版题. /* | 1, -1 | | fn | | 1, 0 | | f ...

  4. Codeforces Round #373 (Div. 2) E. Sasha and Array

    题目链接 分析:矩阵快速幂+线段树 斐波那契数列的计算是矩阵快速幂的模板题,这个也没什么很多好解释的,学了矩阵快速幂应该就知道的东西= =这道题比较巧妙的在于需要用线段树来维护矩阵,达到快速查询区间斐 ...

  5. Codeforces Round #539 (Div. 1) E - Sasha and a Very Easy Test 线段树

    如果mod是质数就好做了,但是做除法的时候对于合数mod可能没有逆元.所以就只有存一下mod的每个质因数(最多9个)的幂,和剩下一坨与mod互质的一部分.然后就能做了.有点恶心. CODE #incl ...

  6. Codeforces Round #200 (Div. 1) D. Water Tree(dfs序加线段树)

    思路: dfs序其实是很水的东西.  和树链剖分一样, 都是对树链的hash. 该题做法是:每次对子树全部赋值为1,对一个点赋值为0,查询子树最小值. 该题需要注意的是:当我们对一棵子树全都赋值为1的 ...

  7. Codeforces Round #323 (Div. 2) D 582B Once Again...(快速幂)

    A[i][j]表示在循环节下标i开头j结尾的最长不减子序列,这个序列的长度为p,另外一个长度为q的序列对应的矩阵为B[i][j], 将两序列合并,新的序列对应矩阵C[i][j] = max(A[i][ ...

  8. Codeforces 719E [斐波那契区间操作][矩阵快速幂][线段树区间更新]

    /* 题意:给定一个长度为n的序列a. 两种操作: 1.给定区间l r 加上某个数x. 2.查询区间l r sigma(fib(ai)) fib代表斐波那契数列. 思路: 1.矩阵操作,由矩阵快速幂求 ...

  9. Codeforces Round #373 (Div. 1)

    Codeforces Round #373 (Div. 1) A. Efim and Strange Grade 题意 给一个长为\(n(n \le 2 \times 10^5)\)的小数,每次可以选 ...

随机推荐

  1. [Spring MVC]学习笔记--@RequestMapping支持的返回类型

    下面针对官方文档列出的支持类型进行举例. (本篇例子存于github上, https://github.com/lemonbar/spring-mvc-requestmapping) 可以直接下载, ...

  2. JavaScript Observer Pattern

    var Users = { list: [], listeners: {}, add: function(name) { this.list.push({name: name}); this.disp ...

  3. 【BZOJ4448】[Scoi2015]情报传递 主席树+LCA

    [BZOJ4448][Scoi2015]情报传递 Description 奈特公司是一个巨大的情报公司,它有着庞大的情报网络.情报网络中共有n名情报员.每名情报员能有若干名(可能没有)下线,除1名大头 ...

  4. eval()和exec()函数的区别

    (1)eval(str [,globals [,locals ])函数将字符串str当成有效Python表达式来求值,并返回计算结果.(2)exec()函数将字符串str当成有效的Python表达式来 ...

  5. jQuery获取input复选框的值

    var ipResolveValue =[]; //定义一个空数组$("input[name='ipResolve']:checked").each(function(){   / ...

  6. spring和hibernate整合时设置自动生成数据库的表

    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFa ...

  7. Java 注解入门

    1.什么是注解 注解的语法: @注解名称; 注解的作用: 用来替代 xml 配置文件; 在 Servlet 3.0 中就可以使用注解来代替配置文件; 注解是由框架来读取使用的; 所有的注解都是 Ann ...

  8. VMware Workstation 虚拟机纯 Linux 终端如何安装 VMware Tools ?

    VMware Workstation 虚拟机纯 Linux 终端如何安装 VMware Tools ? 1.首先在虚拟机设置里面设置一个共享文件夹 2.在虚拟机菜单栏中选择 VMware Tools ...

  9. MySQL中lock与latch的区分

    这里要区分锁中容易令人混淆的概念lock与latch.在数据库中,lock与latch都可以成为锁,但两者有截然不同的含义 latch 一般称为闩锁(轻量级的锁) 因为其要求锁定的时间非常短,若迟勋时 ...

  10. corethink功能模块探索开发(二)让这个模块可安装

    要想让这个模块可安装,只需要在opcmf.php文件中写一些配置数据就行 随便写点 Equip/opencmf.php <?php // 模块信息配置 return array( // 模块信息 ...