codeforces #373(div 2) E (线段树+矩阵快速幂)
来源:互联网 发布:vb编程入门视频教程 编辑:程序博客网 时间:2024/05/22 14:25
Sasha has an array of integers a1, a2, ..., an. You have to performm queries. There might be queries of two types:
- 1 l r x — increase all integers on the segment froml tor by valuesx;
- 2 l r — find , wheref(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 allx > 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 andm (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 integerstpi,li,ri and may bexi (1 ≤ tpi ≤ 2,1 ≤ li ≤ ri ≤ n,1 ≤ xi ≤ 109). Heretpi = 1 corresponds to the queries of the first type andtpi 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 41 1 2 1 12 1 51 2 4 22 2 42 1 5
579
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.
题意:
给一个数组a,有两个操作
1.在l到r区间上对a数组中元素ai全部加x。
2.对l到r上的元素求出f(ai)的和。f(ai)为第ai个斐波那契数,f(1)=1,f(2)=1,f(3)=2.....
思路:
题目很明显是用线段树解决,但是因为斐波那契数列的原因无法直接套线段树。
斐波那契的递推公式是f(n)=f(n-1)+f(n-2),由此可以用矩阵 [1,1] 表示。
[1,0]
区间相加的也可以通过对区间和乘以斐波那契矩阵的x次方来解决。
运用矩阵快速幂的话能将复杂度控制在lgn的效率,最后ac代码运行时间为2s
#include<iostream> #include<stdio.h> #include<math.h> #include<string.h> #include<vector> #include<queue> #include<map> #include<stack> #include<queue> #include<algorithm> using namespace std; const int mod=1e9+7;struct mat{long long mm[2][2];int flag;mat(){memset(mm,0,sizeof(mm));flag=0;}void init(){for(int i=0;i<2;i++)for(int j=0;j<2;j++){if(i==j)mm[i][j]=1;else mm[i][j]=0;}flag=0; }mat operator + (const mat &b)const//矩阵相加{mat c;for(int i=0;i<2;i++)for(int j=0;j<2;j++)c.mm[i][j]=(mm[i][j]+b.mm[i][j])%mod;return c;}mat operator * (const mat &b)const{mat c;memset(c.mm,0,sizeof(c.mm));for(int i=0;i<2;i++)//矩阵相乘for(int j=0;j<2;j++)for(int k=0;k<2;k++)c.mm[i][j]=(c.mm[i][j]+mm[i][k]*b.mm[k][j])%mod;return c;}mat operator ^ (const int &t)const//矩阵快速幂{mat a,res;res.init();int p=t;a.mm[0][1]=a.mm[0][0]=a.mm[1][0]=1;a.mm[1][1]=0;while(p){if(p&1)res=res*a;a=a*a;p>>=1;}return res;}};const int N=100005;mat sumtree[N*4+10],mark[N*4+10];int a[N+10];void build(int start,int end,int node){mark[node].init(); if(start==end) {sumtree[node].init();sumtree[node]=sumtree[node]^(a[start]-1);return;} build(start,(start+end)/2,node*2); build((start+end)/2+1,end,node*2+1);sumtree[node]=sumtree[node*2]+sumtree[node*2+1];}void changetree(int node,mat nn,int start,int end,int left,int right)//运用延迟数组对线段树进行维护{ if(right>=end&&left<=start){sumtree[node]=sumtree[node]*nn;mark[node]=mark[node]*nn;mark[node].flag=1;return;}if(mark[node].flag!=0){mark[node*2]=mark[node*2]*mark[node];mark[node*2].flag=1;mark[node*2+1]=mark[node*2+1]*mark[node];mark[node*2+1].flag=1;sumtree[node*2]=sumtree[node*2]*mark[node];sumtree[node*2+1]=sumtree[node*2+1]*mark[node];mark[node].init();}int m=(start+end)/2;if(left<=m) changetree(node*2,nn,start,m,left,right);if(right>m) changetree(node*2+1,nn,m+1,end,left,right);sumtree[node]=sumtree[node*2]+sumtree[node*2+1];}long long searchsum(int node,int start,int end,int left,int right){ if(left<=start&&right>=end)return sumtree[node].mm[0][0];if(mark[node].flag!=0){mark[node*2]=mark[node*2]*mark[node];mark[node*2].flag=1;mark[node*2+1]=mark[node*2+1]*mark[node];mark[node*2+1].flag=1;sumtree[node*2]=sumtree[node*2]*mark[node];sumtree[node*2+1]=sumtree[node*2+1]*mark[node];mark[node].init();} int mid=(start+end)/2; long long sum=0; if(left<=mid) sum=(sum+searchsum(node*2,start,mid,left,right))%mod; if(right>mid) sum=(sum+searchsum(node*2+1,mid+1,end,left,right))%mod; return sum;}int main(){ freopen("in.txt","r",stdin); freopen("out.txt","w",stdout);int n,m;scanf("%d%d",&n,&m);mat base;base.init();for(int i=0;i<n;i++){scanf("%d",&a[i]);}build(0,n-1,1);while(m--){int type,l,r;scanf("%d%d%d",&type,&l,&r);if(type==1){int xx;scanf("%d",&xx);changetree(1,base^(xx),0,n-1,l-1,r-1);}else printf("%lld\n",(searchsum(1,0,n-1,l-1,r-1))%mod);} return 0;}
- codeforces #373(div 2) E (线段树+矩阵快速幂)
- Codeforces Round #226 (Div. 2) E(矩阵快速幂)
- Codeforces Round #373 (Div. 1)C(线段树维护矩阵,矩阵快速幂)
- Codeforces Round #373 (Div. 2) E. Sasha and Array 线段树维护矩阵
- cf/Codeforces Round #373 div1-C/div2-E Sasha and Array 线段树 + 维护矩阵快速幂
- [Codeforces 719 E. Sasha and Array] 矩阵快速幂+线段树
- CodeForces-719E Sasha and Array(线段树+矩阵快速幂)
- 【CodeForces 719E】【线段树+矩阵快速幂】 Sasha and Array
- CodeForces 719E Sasha and Array 【线段树】【快速矩阵幂】
- CodeForces - 719E Sasha and Array 线段树 + 矩阵快速幂
- Codeforces Round #291 (Div. 2) E - Darth Vader and Tree (DP+矩阵快速幂)
- Codeforces Round #291 (Div. 2)E. Darth Vader and Tree——dp+矩阵快速幂
- 【矩阵快速幂】 Codeforces Round #291 (Div. 2) E. Darth Vader and Tree
- Codeforces Round #291 (Div. 2) E. Darth Vader and Tree 矩阵快速幂
- Codeforces Round #341 (Div. 2) E. Wet Shark and Blocks(dp + 矩阵快速幂)
- Codeforces #341 div 2 E. Wet Shark and Blocks(矩阵快速幂)
- Codeforces Round #341 (Div. 2) E. Wet Shark and Blocks(DP+矩阵快速幂)
- Codeforces Round #341 (Div. 2)E(矩阵快速幂优化dp,好题)
- .NET平台下Redis使用(五)【StackExchange.Redis和Protobuf-net】
- 数据结构--单链表的基本操作(C语言实现)
- [LeetCode-344]Reverse String(c++)
- Linux 统计文本的单词数
- Linux IP地址配置
- codeforces #373(div 2) E (线段树+矩阵快速幂)
- FTP 常用命令
- 【js设计模式笔记---组合模式】
- 怎么绘制属于自己网格信息
- FileZilla server 启动,添加匿名账户
- ifconfig / ifup /ifdown 命令学习
- JAVA入门第一季-7.JAVA中的注释
- cp 复制文件命令
- 【设计模式】 之 单例模式(含实例)