Codeforces Round #373 (Div. 2) E. Sasha and Array 矩阵快速幂+线段树
5 seconds
256 megabytes
standard input
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 l r x — increase all integers on the segment from l to r by values x;
- 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?
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.
For each query of the second type print the answer modulo 109 + 7.
5 4
1 1 2 1 1
2 1 5
1 2 4 2
2 2 4
2 1 5
5
7
9
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 矩阵快速幂+线段树的更多相关文章
- E. Sasha and Array 矩阵快速幂 + 线段树
E. Sasha and Array 这个题目没有特别难,需要自己仔细想想,一开始我想了一个方法,不对,而且还很复杂,然后lj提示了我一下说矩阵乘,然后再仔细想想就知道怎么写了. 这个就是直接把矩阵放 ...
- 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 ...
- Codeforces Round #257 (Div. 2) B. Jzzhu and Sequences (矩阵快速幂)
题目链接:http://codeforces.com/problemset/problem/450/B 题意很好懂,矩阵快速幂模版题. /* | 1, -1 | | fn | | 1, 0 | | f ...
- Codeforces Round #373 (Div. 2) E. Sasha and Array
题目链接 分析:矩阵快速幂+线段树 斐波那契数列的计算是矩阵快速幂的模板题,这个也没什么很多好解释的,学了矩阵快速幂应该就知道的东西= =这道题比较巧妙的在于需要用线段树来维护矩阵,达到快速查询区间斐 ...
- Codeforces Round #539 (Div. 1) E - Sasha and a Very Easy Test 线段树
如果mod是质数就好做了,但是做除法的时候对于合数mod可能没有逆元.所以就只有存一下mod的每个质因数(最多9个)的幂,和剩下一坨与mod互质的一部分.然后就能做了.有点恶心. CODE #incl ...
- Codeforces Round #200 (Div. 1) D. Water Tree(dfs序加线段树)
思路: dfs序其实是很水的东西. 和树链剖分一样, 都是对树链的hash. 该题做法是:每次对子树全部赋值为1,对一个点赋值为0,查询子树最小值. 该题需要注意的是:当我们对一棵子树全都赋值为1的 ...
- 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][ ...
- Codeforces 719E [斐波那契区间操作][矩阵快速幂][线段树区间更新]
/* 题意:给定一个长度为n的序列a. 两种操作: 1.给定区间l r 加上某个数x. 2.查询区间l r sigma(fib(ai)) fib代表斐波那契数列. 思路: 1.矩阵操作,由矩阵快速幂求 ...
- Codeforces Round #373 (Div. 1)
Codeforces Round #373 (Div. 1) A. Efim and Strange Grade 题意 给一个长为\(n(n \le 2 \times 10^5)\)的小数,每次可以选 ...
随机推荐
- 学生成绩管理系统【c】
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<conio.h> #d ...
- form表单提交中文乱码(前台中文到JAVA后台乱码)问题及解决
form表单提交中文乱码(前台中文到JAVA后台乱码)问题及解决 一.问题: 页面输入框中的中文内容,在后台乱码,导致搜索功能失效:(详细可以见后面的重现) 二.原因: 浏览器对于数据的默认编码格式为 ...
- NetCore
正确理解DTO.值对象和POCO https://www.cnblogs.com/redmoon/archive/2015/04/29/4467485.html ASP.NET Core 配置系统 h ...
- jQuery之获取select选中的值
本来以为jQuery("#select1").val();是取得选中的值, 那么jQuery("#select1").text();就是取得的文本. 这是不正确 ...
- Python 编码(一)— Python3
Unicode 什么是 Unicode 标准 unicode 标准 Unicode 为每个字符提供了一个独特的数字,并且跨平台.设备.应用或者编程语言都是通用的. -- 来自 http://unico ...
- JavaWeb 之事务
什么是事务? 事务就是逻辑上的一组操作,组成事务的各个执行单元,操作要么全部成功,要么全部失败. 以转账为例: 张三给李四转账,张三扣1000,李四加1000; 加钱和扣钱两个操作组成了一个事务. 1 ...
- CentOS 7.4 下安装Epel源和Nginx
EPEL (Extra Packages for Enterprise Linux)是基于Fedora的一个项目,为“红帽系”的操作系统提供额外的软件包,适用于RHEL.CentOS和Scientif ...
- windows server2003/2008中权限账户
在windows server 2003与windows server 2008 R2中,查看文件夹权限时,尤其是用cacls命令查看时,经常会见nt authority system这样的用户信息. ...
- (4.14)存储:RAID在数据库存储上的应用
关键词:(4.14)存储:RAID在数据库存储上的应用 转自:http://blog.51cto.com/qianzhang/1251260 随着单块磁盘在数据安全.性能.容量上呈现出的局限,磁盘阵列 ...
- mysql分组查询报错
执行sql group by查询时报错 SELECT id from userz GROUP BY username Expression #1 of SELECT list is not in GR ...