CF446C DZY Loves Fibonacci Numbers

gate

一个数列满足,但它的1,2项不是1,1时,

称它为类斐波那契数列。

它满足以下性质:

若有

1.设,则

2.

证明:

,则

3.前缀和公式:

证明:

 

通过以上性质,发现它可以用线段树维护。

对于每个节点,$sum$表示区间和;

$c1$,$c2$表示这段区间被加上了前两项分别为$c1$,$c2$的类斐波那契数列。

因为初始的数列不一定满足类斐波那契数列的性质,所以把它储存在线段树之外的一个数组里,求值时直接用前缀和求出即可。

注意数据范围!

代码如下

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#define MogeKo qwq
using namespace std;
#define ls (now<<1)
#define rs (now<<1|1)
const int maxn = 2e6+10;
const int mod = 1e9+9;

long long n,m,x,y,op;
long long a[maxn],f[maxn];

struct tree {
    long long sum,c1,c2;
} t[maxn];

int read() {
    int x = 0,f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9') {
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while('0' <= ch && ch <= '9') {
        x = (x<<3)+(x<<1) + ch-'0';
        ch = getchar();
    }
    return x * f;
}

long long getx(long long a1,long long a2,long long x) {
    if(x == 1) return a1;
    if(x == 2) return a2;
    return ( a1*f[x-2] + a2*f[x-1] ) % mod;
}

long long getsum(long long a1,long long a2,long long x) {
    if(x == 1) return a1;
    if(x == 2) return (a1+a2) % mod;
    return ( getx(a1,a2,x+2) - a2 + mod ) % mod;
}

void pushup(int now) {
    t[now].sum = (t[ls].sum + t[rs].sum) % mod;
}

void pushdown(int l,int r,int now) {
    if(!t[now].c1) return;
    int mid = (l+r)>>1;
    long long a1,a2;
    a1 = t[now].c1;
    a2 = t[now].c2;
    t[ls].c1 = (t[ls].c1 + a1) % mod;
    t[ls].c2 = (t[ls].c2 + a2) % mod;
    t[ls].sum = (t[ls].sum + getsum(a1,a2,mid-l+1)) % mod;
    a1 = getx(t[now].c1,t[now].c2,mid-l+2);
    a2 = getx(t[now].c1,t[now].c2,mid-l+3);
    t[rs].c1 = (t[rs].c1 + a1) % mod;
    t[rs].c2 = (t[rs].c2 + a2) % mod;
    t[rs].sum = (t[rs].sum + getsum(a1,a2,r-mid)) % mod;
    t[now].c1 = t[now].c2 = 0;
}

void modify(int L,int R,int l,int r,int now) {
    if(L <= l && r <= R) {
        t[now].c1 = (t[now].c1 + f[l-L+1]) % mod;
        t[now].c2 = (t[now].c2 + f[l-L+2]) % mod;
        t[now].sum = (t[now].sum + getsum(f[l-L+1],f[l-L+2],r-l+1)) % mod;
        return;
    }
    pushdown(l,r,now);
    int mid = (l+r)>>1;
    if(L <= mid) modify(L,R,l,mid,ls);
    if(R > mid) modify(L,R,mid+1,r,rs);
    pushup(now);
}

long long query(int L,int R,int l,int r,int now) {
    long long ans = 0;
    if(L <= l && r <= R) {
        ans = t[now].sum;
        return (ans + mod) % mod;
    }
    pushdown(l,r,now);
    int mid = (l+r)>>1;
    if(L <= mid) ans = (ans + query(L,R,l,mid,ls)) % mod;
    if(R > mid) ans = (ans + query(L,R,mid+1,r,rs)) % mod;
    return (ans+mod)%mod;
}

void init() {
    f[1] = f[2] = 1;
    for(int i = 3; i <= n+2; i++)
        f[i] = (f[i-1] + f[i-2]) %mod;
}

int main() {
    n = read(),m = read();
    for(int i = 1; i <= n; i++) {
        x = read();
        a[i] = (a[i-1] + x) % mod;
    }
    init();
    while(m--) {
        op = read();
        x = read(), y = read();
        if(op == 1) modify(x,y,1,n,1);
        if(op == 2) printf("%lld
",((a[y]-a[x-1]+query(x,y,1,n,1))%mod+mod)%mod);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/mogeko/p/12410655.html