codeforces 446C DZY Loves Fibonacci Numbers 线段树

假如F[1] = a, F[2] = B, F[n] = F[n - 1] + F[n - 2]。

写成矩阵表示形式可以很快发现F[n] = f[n - 1] * b + f[n - 2] * a。 f[n] 是斐波那契数列

也就是我们如果知道一段区间的前两个数增加了多少,可以很快计算出这段区间的第k个数增加了多少

通过简单的公式叠加也能求和

F[n]  = f[n - 1] * b + f[n - 2] * a

F[n - 1] = f[n - 2] * b + f[n - 3] * a

.....

F[3] = f[2] * b + f[1] * a

F[2] = 1 * b    +        0

F[1] =    0       +        a

令G[n] = 0 + 1 + f[2] + f[3] + .... + f[n - 1]

K[n]  = 1 + 0 + f[1] + f[2] + .... f[n - 2] ,那么F[n] = G[n] * b + K[n] * a

线段树结点维护a,b两个延迟标记,分别表示第一个数和第二个数增加了多少

注意在PushDown和update的时候还要通过F[n]  = f[n - 1] * b + f[n - 2] * a计算出右子节点的前两个数应该增加的值

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>

using namespace std;
typedef long long LL;

const int maxn = 3e5 + 10;
const int mod = 1e9 + 9;
#define lson idx << 1, l, mid
#define rson idx << 1 | 1, mid + 1, r

LL f[maxn], F[maxn], G[maxn];
void init() {
    f[1] = G[1] = 1;
    F[0] = 1;
    F[1] = 1;
    for(int i = 2; i < maxn; i++) {
        f[i] = (f[i - 1] + f[i - 2]) % mod;
        G[i] = (G[i - 1] + f[i]) % mod;
        F[i] = (F[i - 1] + f[i - 1]) % mod;
    }
    // F[i] = 1 + 0 + f[1] + f[2] + f[3] + ....f[i - 1]
    // G[i] = 0 + f[1] + f[2] + f[3] + ....f[i]
}
LL sum[maxn << 2];
LL a[maxn << 2], b[maxn << 2];
void PushUp(int idx) {
    sum[idx] = (sum[idx << 1] + sum[idx << 1 | 1]) % mod;
}
void build(int idx, int l, int r) {
    a[idx] = b[idx] = 0;
    if(l == r) {
        scanf("%I64d", &sum[idx]);
    } else {
        int mid = (r + l) >> 1;
        build(lson);
        build(rson);
        PushUp(idx);
    }
}

void maintain(int idx, int l,int r, int v1, int v2) {
    int len = r - l + 1;
    a[idx] = (a[idx] + v1) % mod;
    b[idx] = (b[idx] + v2) % mod;
    sum[idx] = (sum[idx] + G[len - 1] * v2 % mod + F[len - 1] * v1 % mod) % mod;
}
void PushDown(int idx, int l, int r) {
    if(a[idx] != 0 || b[idx] != 0) {
         int mid = (r + l) >> 1;
         maintain(lson, a[idx], b[idx]);
         int len = mid - l + 1;
         int v1 = (f[len] * b[idx] + f[len - 1] * a[idx]) % mod;
         int v2 = (f[len + 1] * b[idx] + f[len] * a[idx]) % mod;
         maintain(rson, v1, v2);
         a[idx] = b[idx] = 0;
    }
}
void update(int idx, int l, int r, int tl, int tr, int v1, int v2) {
    if(tl <= l && tr >= r) {
        maintain(idx, l, r, v1, v2);
    } else {
        PushDown(idx, l, r);
        int mid = (r + l) >> 1;
        if(tl <= mid) update(lson, tl, tr, v1, v2);
        if(tr > mid) {
            LL h1 = v1, h2 = v2;
            if(tl <= mid) {
                int len = mid - max(tl,l) + 1;
                h1 = (f[len] * v2 + f[len - 1] * v1) % mod;
                h2 = (f[len + 1] * v2 + f[len] * v1) % mod;
            }
            update(rson, tl, tr, h1, h2);
        }
        PushUp(idx);
    }
}
LL query(int idx, int l, int r, int tl, int tr) {
    if(tl <= l && tr >= r) return sum[idx];
    else {
        PushDown(idx, l, r);
        int mid = (r + l) >> 1;
        LL ans = 0;
        if(tl <= mid) ans = (ans + query(lson, tl, tr)) % mod;
        if(tr > mid) ans = (ans + query(rson, tl, tr)) % mod;
        return ans;
    }
}
int main() {
    init();
    int n, m;
    scanf("%d%d", &n, &m);
    build(1, 1, n);
    for(int i = 1; i <= m; i++) {
        int op, l, r;
        scanf("%d%d%d", &op, &l, &r);
        if(op == 1) update(1, 1, n, l, r, 1, 1);
        else {
            LL ans = query(1, 1, n, l, r);
            printf("%I64d\n", ans);
        }
    }
    return 0;
}

codeforces 446C DZY Loves Fibonacci Numbers 线段树

时间: 2024-08-02 15:13:47

codeforces 446C DZY Loves Fibonacci Numbers 线段树的相关文章

codeforces 446C DZY Loves Fibonacci Numbers(数学 or 数论+线段树)

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

codeforces 446C DZY Loves Fibonacci Numbers 数论+线段树成段更新

DZY Loves Fibonacci Numbers Time Limit:4000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Appoint description:  System Crawler  (2014-07-14) Description In mathematical terms, the sequence Fn of Fibonacci numbers is defi

Codeforces446C DZY Loves Fibonacci Numbers(线段树 or 分块?)

第一次看到段更斐波那契数列的,整个人都不会好了.事后看了题解才明白了一些. 首先利用二次剩余的知识,以及一些数列递推式子有下面的 至于怎么解出x^2==5(mod 10^9+9),我就不知道了,但是要用的时候可以枚举一下,把这些参数求出来之后就题目就可以转化为维护等比数列. 由于前面的常数可以最后乘,所以就等于维护两个等比数列好了. 下面我们来看如何维护一个等比数列.假如我对区间[L,R]的加上1,2,4,8...2^n的话,那么我只需要加一个标记x表示这个区间被加了多少次这样的2^n. 举个例

CF446C DZY Loves Fibonacci Numbers 线段树 + 数学

code: #include <bits/stdc++.h> #define N 400004 #define LL long long #define lson now<<1 #define rson now<<1|1 #define setIO(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) using namespace

Codeforces 444C DZY Loves Colors 水线段树

题目链接:点击打开链接 水.. #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <math.h> #include <set> #include <vector> #include <map> using namespace std; #define ll long long #defi

[CodeForces - 447E] E - DZY Loves Fibonacci Numbers

E  DZY Loves Fibonacci Numbers 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 consist

Codeforces446C - DZY Loves Fibonacci Numbers

Portal Description 给出一个\(n(n\leq3\times10^5)\)个数的序列,进行\(m(m\leq3\times10^5)\)次操作,操作有两种: 给区间\([L,R]\)加上一个斐波那契数列,即\(\{a_L,a_{L+1},...,a_R\} \rightarrow \{a_L+F_1,a_{L+1}+F_2,...,a_R+F_{R-L+1}\}\) 询问区间\([L,R]\)的和,对\(10^9+9\)取模. 斐波那契数列:\(F_1=1,F_2=2\)且满足

Codeforces Round #FF (Div. 2) E. DZY Loves Fibonacci Numbers(斐波那契的定理+线段树)

/* 充分利用了菲波那切数列的两条定理: ①定义F[1] = a, F[2] = b, F[n] = F[n - 1] + F[n - 2](n≥3). 有F[n] = b * fib[n - 1] + a * fib[n - 2](n≥3),其中fib[i]为斐波那契数列的第 i 项. ②定义F[1] = a, F[2] = b, F[n] = F[n - 1] + F[n - 2](n≥3). 有F[1] + F[2] + -- + F[n] = F[n + 2] - b 这题还有一个事实,

【CF446C】DZY Loves Fibonacci Numbers (线段树 + 斐波那契数列)

Description ? 看题戳我 给你一个序列,要求支持区间加斐波那契数列和区间求和.\(~n \leq 3 \times 10 ^ 5, ~fib_1 = fib_2 = 1~\). Solution ? 先来考虑一段斐波那契数列如何快速求和,根据性质有 \[ \begin {align} fib_n &= fib_{n - 1} + fib_{n - 2} \ &= fib_ {n - 2} + fib_{n - 3} + fib_{n - 2} \ &= fib_{n -