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)\)的小数,每次可以选 ...
随机推荐
- 【BZOJ1053】[HAOI2007]反素数ant 暴力
[BZOJ1053][HAOI2007]反素数ant Description 对于任何正整数x,其约数的个数记作g(x).例如g(1)=1.g(6)=4.如果某个正整数x满足:g(x)>g(i) ...
- The E-pang Palace(暴力几何)
//暴力的几何题,问,n个点可以组成的矩形,不相交,可包含的情况下,最大的面积,还有就是边一定与 x y 轴平行,所以比较简单了 //暴力遍历对角线,搜出所有可能的矩形,然后二重循环所有矩形,判断一下 ...
- CSS 关于让页面的高度达到电脑屏幕的底部
.sidebar:before {content: "";display: block;width: 190px;position: fixed;bottom: 0;top: 0; ...
- Stolz–Cesàro theorem
w http://planetmath.org/sites/default/files/texpdf/33795.pdf Stolz–Cesàro theorem - Wikipedia https ...
- JavaWeb 之监听器
1. JavaWeb 监听器概述 在 JavaWeb 被监听的事件源为: ServletContext, HttpSession, ServletRequest, 即三大域对象. 监听域对象" ...
- JavaScript实现自适应窗口大小的网页
<!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content ...
- 内置函数(Day16)
现在python一共为我们提供了68个内置函数.它们就是python提供给你直接可以拿来使用的所有函数 内置函数 abs() divmod() input() open() stati ...
- iframe 跨域请求
iframe.contentWindow 兼容各个浏览器,可取得子窗口的 window 对象. iframe.contentDocument Firefox 支持,> ie8 的ie支持.可取得 ...
- java WordUtils word文档工具类
package com.sicdt.library.core.utils; import java.io.ByteArrayOutputStream; import java.io.IOExcepti ...
- 【leetcode刷题笔记】Regular Expression Matching
Implement regular expression matching with support for '.' and '*'. '.' Matches any single character ...