zoukankan      html  css  js  c++  java
  • CF446C DZY Loves Fibonacci Numbers

    CF446C DZY Loves Fibonacci Numbers

    洛谷评测传送门

    题目描述

    In mathematical terms, the sequence F_{n}F**n of Fibonacci numbers is defined by the recurrence relation

    F_{1}=1; F_{2}=1; F_{n}=F_{n-1}+F_{n-2} (n>2). DZY loves Fibonacci numbers very much. Today DZY gives you an array consisting of nn integers: a_{1},a_{2},...,a_{n}a1,a2,...,a**n . Moreover, there are mm queries, each query has one of the two types:

    1. Format of the query " 1 l r1 l r ". In reply to the query, you need to add F_{i-l+1}F**il+1 to each element a_{i}a**i , where l<=i<=rl<=i<=r .
    2. Format of the query " 2 l r2 l r ". In reply to the query you should output the value of img modulo 1000000009 (10^{9}+9) .

    Help DZY reply to all the queries.

    输入格式

    The first line of the input contains two integers nn and mm ( 1<=n,m<=3000001<=n,m<=300000 ). The second line contains nn integers a_{1},a_{2},...,a_{n} (1<=a_{i}<=10^{9}) — initial array aa .

    Then, mm 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<=n1<=l<=r<=n holds.

    输出格式

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

    题意翻译

    题面大意:给出一个数列,每次可以选取一个区间,按顺序加上第i个Fibonacci Numbers(斐波那契数)进行更新,也可以查询某一个区间的总和。

    感谢@char32_t 提供的翻译

    输入输出样例

    输入 #1复制

    输出 #1复制

    说明/提示

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

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

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

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

    题解:

    2019.11.5模拟赛T3 40分场

    (O(n^2))的做法能水10分,普通线段树毫无优化能跑30分。感谢出题人@littleseven

    一看是黑题顿时毫无思路。因为这道题涉及到的知识点:线段树+(Fibonacci)数列是联赛范围内,所以它就这样被收进了联赛模拟赛中。

    介绍一下正解:

    首先我们能想到,区间修改区间查询一定需要线段树。而且这道题难住我们的点就是如何维护修改操作,换句话说,如何进行下传标记。

    但是我们稍微动动脑能发现这个性质:(我在考场上也推出来了)

    对于一个要修改的区间([l,r])中的第(x)项,它需要加上这一项:(fib_{x-l+1})(fib)表示斐波那契数列。

    而斐波那契数列有这样的性质:(很重要,虽然蒟蒻也是做了这道题才知道)

    [fib[n+m]=fib[n+1]fib[m]+fib[n]fib[m-1] ]

    那么对于这个位置(x),设(n=-l,m=x+1),它加上了:

    [fib[x-l+1]=fib[1-l]fib[x+1]+fib[x]fib[-l] ]

    那么对于线段树上的节点,我们需要维护两个标记:(add1[i],add2[i]),分别统计对于一个区间为([l,r])的节点,(add1(fib_{l+1}+fib_{l+2}+cdots+fib_{r+1}))(add2(fib_{l}+fib_{l+1}+cdots+fib_{r}))

    修改的时候,给(add1)加上(fib_{-l+1}),给(add2)加上(fib_{-l}),然后进行线段树的正常(pushdown)操作即可。

    代码:

    #include<cstdio>
    #define lson pos<<1
    #define rson pos<<1|1
    using namespace std;
    const int maxn=3*1e5+10;
    const int mod=1e9+9;
    char *p1,*p2,buf[100000];
    #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
    int read()
    {
        int x=0,f=1;
        char ch=nc();
        while(ch<48){if(ch=='-')f=-1;ch=nc();}
        while(ch>47)    x=(((x<<2)+x)<<1)+ch-48,ch=nc();
        return x*f;
    }
    int n,m;
    int a[maxn],sum[maxn],fib[maxn],ffib[maxn];
    int tree[maxn<<2],add1[maxn<<2],add2[maxn<<2];
    void fibonacci()
    {
        fib[1]=fib[2]=sum[1]=ffib[1]=1;
        sum[2]=2;
        ffib[2]=mod-1;
        for(int i=3;i<=n+1;i++)
        {
            fib[i]=(fib[i-1]+fib[i-2])%mod;
            sum[i]=(sum[i-1]+fib[i])%mod;
            ffib[i]=(i&1)?fib[i]:mod-fib[i];
        }
    }
    void build(int pos,int l,int r)
    {
        int mid=(l+r)>>1;
        if(l==r)
        {
            tree[pos]=a[l]%mod;
            return;
        }
        build(lson,l,mid);
        build(rson,mid+1,r);
        tree[pos]=(tree[lson]+tree[rson])%mod;
    }
    void mark(int pos,int l,int r,int a1,int a2)
    {
        add1[pos]=(add1[pos]+a1)%mod;
        add2[pos]=(add2[pos]+a2)%mod;
        tree[pos]=(tree[pos]+1ll*(sum[r+1]-sum[l]+mod)%mod*a1%mod)%mod;
        tree[pos]=(tree[pos]+1ll*(sum[r]-sum[l-1]+mod)%mod*a2%mod)%mod;
    }
    void pushdown(int pos,int l,int r)
    {
        int mid=(l+r)>>1;
        mark(lson,l,mid,add1[pos],add2[pos]);
        mark(rson,mid+1,r,add1[pos],add2[pos]);
        add1[pos]=add2[pos]=0;
    }
    void update(int pos,int l,int r,int x,int y,int a1,int a2)
    {
        int mid=(l+r)>>1;
        if(x<=l && r<=y)
        {
            mark(pos,l,r,a1,a2);
            return;
        }
        pushdown(pos,l,r);
        if(x<=mid)
            update(lson,l,mid,x,y,a1,a2);
        if(y>mid)
            update(rson,mid+1,r,x,y,a1,a2);
        tree[pos]=(tree[lson]+tree[rson])%mod;
    }
    int query(int pos,int l,int r,int x,int y)
    {
        int ret=0;
        int mid=(l+r)>>1;
        if(x<=l && r<=y)
            return tree[pos]%mod;
        pushdown(pos,l,r);
        if(x<=mid)
            ret=(ret+query(lson,l,mid,x,y))%mod;
        if(y>mid)
            ret=(ret+query(rson,mid+1,r,x,y))%mod;
        return ret%mod;
    }
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=n;i++)
            a[i]=read();
        fibonacci();
        build(1,1,n);
        for(int i=1;i<=m;i++)
        {
            int opt,l,r;
            opt=read();l=read();r=read();
            if(opt==1)
                update(1,1,n,l,r,ffib[l-1],ffib[l]);
            else
                printf("%d
    ",query(1,1,n,l,r));
        }
        return 0;
    }
    
  • 相关阅读:
    PostgreSQL数据库
    phpcms网站搬家 至 服务器 完整并且详细过程
    phpcms网页替换验证码功能 及 搜索功能
    用phpcms切换中英文网页的方法(不用解析二级域名)、phpcms完成pc和手机端切换(同一域名)
    php判断手机段登录,以及phpcms手机PC双模板调用
    php 手动搭建环境
    phpcms内容页替换
    phpcms列表页替换
    phpcms首页替换
    phpcms栏目点击选中
  • 原文地址:https://www.cnblogs.com/fusiwei/p/11799491.html
Copyright © 2011-2022 走看看