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)\)的小数,每次可以选 ...
随机推荐
- Highway
Highway Accepted : 78 Submit : 275 Time Limit : 4000 MS Memory Limit : 65536 KB Highway In ICPCC ...
- JS将秒转换为 天
function SecondToDate(msd) { var time =msd if (null != time && " ...
- django startapp报 maximum recursion depth exceeded
报错截图如下: 解决办法:修改指定路径下的functools.py文件的def total_ordering(cls):方法: 原来的样子: convert = { '__lt__': [('__gt ...
- PHP判断是手机端访问还是PC端访问网站
Mobile_Detect 是一个轻量级的开源移动设备(手机)检测的 PHP Class, 它使用 User-Agent 中的字符串,并结合 HTTP Header,来检测移动设备环境. 这个设备检测 ...
- Android系统移植与调试之------->如何修改Android系统默认显示【开发者选项】并默认打开【USB调试】和【未知来源】开关
今天有个用户对[设置]有个特殊的要求,即: 1.开机的时候默认显示[开发者选项]并打开[USB调试]开关 ([Developer options]-->[USB debugging]) 2 ...
- jQuery 查找标签
1 基本选择器 2 基本筛选器 3 属性选择器 4 间接选择 1 基本选择器 //id选择器: $("#id") //标签选择器: $("tagName") / ...
- 2. 安装 Kerberos
2.1. 环境配置 安装kerberos前,要确保主机名可以被解析. 主机名 内网IP 角色 Vmw201 172.16.18.201 Master KDC Vmw202 172.16.18.202 ...
- golang接收get/post请求并返回json数据
// @router /d2 [post] func (c *MainController) D2() { // jsoninfo := c.GetString("ok") // ...
- windows server2003/2008中权限账户
在windows server 2003与windows server 2008 R2中,查看文件夹权限时,尤其是用cacls命令查看时,经常会见nt authority system这样的用户信息. ...
- 爬虫、网页测试 及 java servlet 测试框架等介绍
scrapy 抓取网页并存入 mongodb的完整示例: https://github.com/rmax/scrapy-redis https://github.com/geekan/scrapy-e ...