Codeforces Round #FF (Div. 1) C - DZY Loves Fibonacci Numbers

C. DZY Loves Fibonacci Numbers
time limit per test
4 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

In mathematical terms, the sequence Fn of Fibonacci numbers is defined by the recurrence relation

F1 = 1; F2 = 1; Fn = Fn - 1 + Fn - 2 (n > 2).

DZY loves Fibonacci numbers very much. Today DZY gives you an array consisting of n integers: a1, a2, ..., an. Moreover, there are mqueries, each query has one of the two types:

  1. Format of the query "l r". In reply to the query, you need to add Fi - l + 1 to each element ai, where l ≤ i ≤ r.
  2. Format of the query "l r". In reply to the query you should output the value of  modulo 1000000009 (109 + 9).

Help DZY reply to all the queries.

Input

The first line of the input contains two integers n and m (1 ≤ n, m ≤ 300000). The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 109) — initial array a.

Then, m lines follow. A single line describes a single query in the format given in the statement. It is guaranteed that for each query inequality 1 ≤ l ≤ r ≤ n holds.

Output

For each query of the second type, print the value of the sum on a single line.

Sample test(s)
input
4 4
1 2 3 4
1 1 4
2 1 4
1 2 4
2 1 3
output
17
12
Note

After the first query, a = [2, 3, 5, 7].

For the second query, sum = 2 + 3 + 5 + 7 = 17.

After the third query, a = [2, 4, 6, 9].

For the fourth query, sum = 2 + 4 + 6 = 12.


题意:有n个数,每一次操作可能是在下标为[l,r]的数对应加上f[1],f[2],f[3]....f[r-l+1],一个操作是询问[l,r]的数的和是多少。


思路:首先发现mod=1e9+9. 那么在该系下5是二次剩余。这样我们能把sqrt(5)换成一个整数来运算。由于斐波那契数列是两个等比数列组合而成的。所以那个第一个操作就是相当于在[l,r]上对应加上一个等比数列。 我们在线段树的每个节点只要存等比数列的首项就行了,因为线段树的每个节点的长度是固定的,所以加上一段等比数列 就是 + a0(1-q^n)/(1-q) 这里面除了a0不是固定的,其他是固定的。这样基本思路就有了。感觉边界条件讨论起来很吃力,难道真的是老了吗?


代码:

#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <string.h>
#include <string>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
using namespace std;
#define mp make_pair
#define rep(i,n) for(int i=0;i<n;++i)
#define clr(a,x) memset(a,x,sizeof(a))
#define LL long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int N=300000+5;
const int mod=1e9+9;
const LL sqr=383008016;

LL sum[N<<2],col[N<<2][2];
LL a[N],b[N],F[N],c;
LL Sa[N],Sb[N];

LL qpow(LL base,LL p)
{
    LL ret=1;
    while(p>0) {
        if(p&1) ret=(ret*base)%mod;
        base=(base*base)%mod;
        p>>=1;
    }
    return ret;
}


void pushdown(int l,int r,int m,int rt)
{
    int ls=rt<<1,rs=rt<<1|1;
    if(col[rt][0]) {
        col[ls][0]+=col[rt][0]; col[rs][0]+=(col[rt][0]*a[m+1-l])%mod;
        col[ls][0]%=mod; col[rs][0]%=mod;
        sum[ls]+= ((c*col[rt][0])%mod*Sa[m-l])%mod;
        sum[rs]+=(((((c*col[rt][0])%mod)*a[m+1-l])%mod)*Sa[r-m-1])%mod;
    }
    if(col[rt][1]) {
        col[ls][1]+=col[rt][1]; col[rs][1]+=(col[rt][1]*b[m-l+1])%mod;
        col[ls][1]%=mod; col[rs][1]%=mod;
        sum[ls] -= ((c*col[rt][1])%mod*Sb[m-l])%mod;
        sum[rs] -=(((((c*col[rt][1])%mod)*b[m+1-l])%mod)*Sb[r-m-1])%mod;
    }
    sum[ls]%=mod; sum[rs]%=mod;
    if(sum[ls]<0) sum[ls]+=mod;
    if(sum[rs]<0) sum[rs]+=mod;
    col[rt][0]=col[rt][1]=0;
}

inline void pushup(int rt) { sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%mod; }

void update1(int p,int x,int l,int r,int rt)
{
    if(l==r) { sum[rt]+=x; return; }
    int m=(l+r)>>1;
    if(p<=m) update1(p,x,lson);
    else update1(p,x,rson);
    pushup(rt);
}

void update2(int L,int R,int k,int l,int r,int rt)
{
    if(L==l&&r==R) {
        col[rt][0]=(col[rt][0]+a[k])%mod;
        col[rt][1]=(col[rt][1]+b[k])%mod;
        sum[rt]=(sum[rt]+F[k+r-l]-F[k-1])%mod;
        if(sum[rt]<0) sum[rt]+=mod;
        return;
    }
    int m=(l+r)>>1;
    pushdown(l,r,m,rt);
    if(R<=m) update2(L,R,k,lson);
    else if(L>m) update2(L,R,k,rson);
    else {
        update2(L,m,k,lson);
        update2(m+1,R,k+m-L+1,rson);
    }
    pushup(rt);
}

LL query(int L,int R,int l,int r,int rt)
{
    if (L<=l&&r<=R) return sum[rt];
    int m=(l+r)>>1;
    LL ret=0;
    pushdown(l,r,m,rt);
    if(L<=m) ret+=query(L,R,lson);
    if(m<R) ret+=query(L,R,rson);
    pushup(rt);
    return ret%mod;
}

void pre_init()
{
    c=qpow(sqr,mod-2);
    F[1]=F[2]=1;
    for(int i=3;i<N;++i) F[i]=(F[i-1]+F[i-2])%mod;
    for(int i=2;i<N;++i) F[i]=(F[i-1]+F[i])%mod;

    LL x=((1+sqr)*qpow(2,mod-2))%mod;
    a[0]=1;
    for(int i=1;i<N;++i) a[i]=(a[i-1]*x)%mod;
    x=((1-sqr)*qpow(2,mod-2))%mod;
    if(x<0) x+=mod;
    b[0]=1;
    for(int i=1;i<N;++i) b[i]=(b[i-1]*x)%mod;

    Sa[0]=Sb[0]=1;
    for(int i=1;i<N;++i) Sa[i]=(Sa[i-1]+a[i])%mod;
    for(int i=1;i<N;++i) Sb[i]=(Sb[i-1]+b[i])%mod;

}

int main()
{
    pre_init();
    int n,q;
    cin>>n>>q;
    for(int i=1;i<=n;++i) {
        int x; scanf("%d",&x);
        update1(i,x,1,n,1);
    }
    while(q--){
        int o,l,r; scanf("%d%d%d",&o,&l,&r);
        if(o==2) printf("%I64d\n",query(l,r,1,n,1));
        else  update2(l,r,1,1,n,1);
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值