【CodeForces 719E】【线段树+矩阵快速幂】 Sasha and Array

来源:互联网 发布:python 抢购脚本 编辑:程序博客网 时间:2024/05/22 14:34

传送门:E. Sasha and Array

描述:

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) = 1f(2) = 1f(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 0001 ≤ 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 ≤ 21 ≤ 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 41 1 2 1 12 1 51 2 4 22 2 42 1 5
output
579
Note

Initially, array a is equal to 11211.

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

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.

题意:
给出有n个元素的数列ai(1<=i<=n)以及m次操作,操作分为两种:①将区间[l,r]的数加x;②询问∑f(ai)(l<=i<=r),其中f(x)是斐波那契数列的第x个数
题解:
斐波那契数列可以由2*2矩阵A={1 1,1 0}相乘得到,因此可以想到用线段树存储矩阵,每次更新加x就可以用乘以A^x代替

这题写的有点气,初始化没弄对,调半天_(:зゝ∠)_
代码:
#include <bits/stdc++.h>#define pr(x) cout << #x << "= " << x << "  " ;#define pl(x) cout << #x << "= " << x << endl;#define lson l, m, rt<<1  #define rson m+1, r, rt<<1|1 #define ll __int64using  namespace  std;template<class T> void read(T&num) {    char CH; bool F=false;    for(CH=getchar();CH<'0'||CH>'9';F= CH=='-',CH=getchar());    for(num=0;CH>='0'&&CH<='9';num=num*10+CH-'0',CH=getchar());    F && (num=-num);}const ll M=1e9+7;const int maxn=1e5+10;struct Matrix{    ll v[2][2];};void init(Matrix& ad){  ad.v[0][0]=1; ad.v[0][1]=1;  ad.v[1][0]=1; ad.v[1][1]=0;}Matrix mtAdd(Matrix A, Matrix B){        // 求矩阵 A + B  int i, j;  Matrix C;  for(i = 0; i < 2; i ++)    for(j = 0; j < 2; j ++){      C.v[i][j] = (A.v[i][j] + B.v[i][j]) % M;    }  return C;}Matrix mtMul(Matrix A, Matrix B){        // 求矩阵 A * B  int i, j, k;  Matrix C;  for(i = 0; i < 2; i ++)    for(j = 0; j < 2; j ++){      C.v[i][j] = 0;      for(k = 0; k < 2; k ++){        C.v[i][j] = (A.v[i][k] * B.v[k][j] + C.v[i][j]) % M;      }    }  return C;}Matrix mtPow(Matrix A, int k){           // 求矩阵 A ^ k  if(k == 0) {    memset(A.v, 0, sizeof(A.v));    for(int i = 0; i < 2; i ++){      A.v[i][i] = 1;    }    return A;  }  if(k == 1) return A;  Matrix C = mtPow(A, k / 2);  if(k % 2 == 0) {    return mtMul(C, C);  }  else {    return mtMul(mtMul(C, C), A);  }}Matrix sum[maxn<<2],add[maxn<<2],A;void PushUp(int rt){  sum[rt]=mtAdd(sum[rt<<1], sum[rt<<1|1]);}void PushDown(int rt){  add[rt<<1]=mtMul(add[rt<<1], add[rt]);  add[rt<<1|1]=mtMul(add[rt<<1|1], add[rt]);  sum[rt<<1]=mtMul(sum[rt<<1], add[rt]);  sum[rt<<1|1]=mtMul(sum[rt<<1|1], add[rt]);  add[rt]=mtPow(A, 0);}void build(int l, int r,int rt){  add[rt]=mtPow(A, 0);//初始化为单位矩阵  sum[rt]=mtPow(A, 0);   if(l==r){    int x;read(x);    sum[rt]=mtPow(A, x-1);     return;  }   int m=(l+r)>>1;  build(lson);    build(rson);    PushUp(rt); }void update(int L,int R,Matrix c,int l,int r,int rt){  if(L<=l && R>=r){      sum[rt]=mtMul(sum[rt], c);      add[rt]=mtMul(add[rt], c);     return;    }   PushDown(rt);  int m=(l+r)>>1;  if(L<=m)update(L, R, c, lson);  if(R>m)update(L, R, c, rson);  PushUp(rt);}ll query(int L,int R,int l, int r,int rt){  if(L<=l && R>=r){    return sum[rt].v[0][0];  }  PushDown(rt);  int m=(l+r)>>1;  ll ret=0;  if(L<=m)ret=(ret+query(L, R, lson))%M;  if(R>m)ret=(ret+query(L, R, rson))%M;  PushUp(rt);  return ret;}//debug用void print(int l,int r,int rt){    if(l==r){      for(int i=0;i<2;i++){        for(int j=0;j<2;j++)          printf("%I64d ",sum[rt].v[i][j]);        printf("\n");      }      printf("\n");      return;    }    int m=(l+r)>>1;    print(lson);    print(rson);  }  int  main(){  #ifndef ONLINE_JUDGE  freopen("in.txt","r",stdin);  #endif  int n,m;  init(A);  read(n);read(m);   build(1, n, 1);  int op,a,b;  while(m--){    read(op);read(a);read(b);    if(op==1){      int x;read(x);      update(a, b, mtPow(A, x), 1, n, 1);    }    else{      printf("%I64d\n", query(a, b, 1, n, 1));    }  }  return 0;}



0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 公司变更法人新刻法人章怎么办 个体户年报第一年忘了报怎么办 别人说娃名字起大了怎么办? 综英美我能怎么办我也很绝望 两个人不合适且结了婚怎么办 国税局寄来的邮件没收到怎么办 新疆办理暂住证有案底不办给怎么办 我的驾驶证吊销了车年审怎么办 好几个超速分不够扣了怎么办 刚拿c1驾照扣6分怎么办 别人开我车扣12分怎么办 办健康证大便拉不出来怎么办 欠信用卡钱被网上通缉抓到后怎么办 上海房子卖了户口没地方迁怎么办 没有户口本在北京身份证丢了怎么办 武汉科目四考试居住证过期了怎么办 农行卡密码输错3次怎么办 驾照罚款缴纳了网上没消怎么办 外地驾驶证分数扣12分了怎么办 有生产日期的赠品在超市过期怎么办 6年免检车辆逾期未年检怎么办 行驶证检验有效期过期2年怎么办 骑摩托车忘带驾驶证和行驶证怎么办 驾驶证逾期未审验怎么办有什么后果 车祸至人腿部骨折沒钱偿还的怎么办 我有c4驾驶证想办c3怎么办 驾驶证和行驶证被交警扣了怎么办 行驶证被交警弄丢了怎么办 没带行驶证让警察发现怎么办 首尔转机换票换乘怎么办过境签证 驾驶证约考帐号与登密码丢失怎么办 考驾照的时候预约密码忘了怎么办 考驾照的预约密码忘了怎么办 摩托车不能挂档不能摘挡了怎么办 身份证丢失了派出所不给挂失怎么办 快递员在中午还送货夏天怎么办啊 驾照一个记分周期扣满12分怎么办 佛山南海车管所怎么办替人消分流程 福州快处中心几流程要怎么办 被对方追尾了对方只有交强险怎么办 摩托车行驶证年检过期一年半怎么办