zoukankan      html  css  js  c++  java
  • codeforces 446C-- 斐波那契的结论

    af[n-1] + b[n-2] (a >= b 且a, b都是斐波那契数)  那么这个式子就表示 以a b为前两项的斐波那契数的第n项斐波那契数 

    http://blog.csdn.net/qq_24451605/article/details/48105763

    题目链接:

    codeforces 446C


    题目大意:

    给出一个数列,每次可以选取一个区间,按顺序加上第i个菲波那契数进行更新,也可以查询某一个区间的总和。


    题目分析:

      • 首先要做这个题必须了解菲波那契数的一些基本的性质 
        • 首先我们是可以通过每个菲波那契数列的前两项O(1)的获得任意一项的数值和任意i项的前缀和。
        • 然后就是两个菲波那契数列相加之后依旧是一个菲波那契数列,只是前两项的值变化,分别变为了两个菲波那契数列前两项的和。
        • 利用这两个性质之后就是线段树很基本的操作了,用f1,f2懒操作当前要加的数列的前两项的值,sum记录当前区间的总和。
      • 下面简单证明前面提到的两个性质: 
        • 第一性质证明如下: 
          首先我们可以预处理除前两项都为1的菲波那契数列的各项的值。然后我们可以通过afib[n1]+bfib[n2]获得以a,b为前两项的第n项的值。因为我们可以先看a作为第一项,在要求的第n个数中出现了多少次?我们可以将第一项标记为1,第二项作为0,也就是a出现的次数,那么对于第i个数中存在a的个数,就等于fib[n-1],因为在做递推的过程中a的数目比fib的数值相当于慢了一步,关于b的个数同理可证,那么公式成立。 
          然后我们对于菲波那契数中某一项: 
          {fib[n]=fib[n1]+fib[n2]fib[n1]=fib[n2]+fib[n3]fib[n]=fib[n2]++fib[3]+2fib[2]+fib[1]i=1nfib[i]=fib[n+2]fib[2]

          第二个性质其实很容易证明,两个菲波那契数列相加只不过是修改了前两项的值,故不再赘述,有了这两个性质,就很方便来维护菲波那契数列的一些的操作了。 
    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #define MAX 300007
    
    using namespace std;
    
    typedef long long LL;
    
    int n,m,a[MAX];
    const LL mod = 1e9+9;
    LL fib[MAX];
    
    struct Tree
    {
        int l,r;
        LL sum,f1,f2;
    }tree[MAX<<2];
    
    void push_up ( int u )
    {
        tree[u].sum = tree[u<<1].sum + tree[u<<1|1].sum;
        tree[u].sum %= mod;
    }
    
    void build ( int u , int l , int r )
    {
        tree[u].l = l;
        tree[u].r = r;
        tree[u].f1 = tree[u].f2 = 0;
        if ( l == r )
        {
            tree[u].sum = a[l];
            return;
        }
        int mid = l+r>>1;
        build ( u<<1 , l , mid );
        build ( u<<1|1 , mid+1 , r );
        push_up ( u );
    }
    
    void init ( )
    {
        fib[1] = fib[2] = 1;
        for ( int i = 3 ; i < MAX ; i++ )
        {
            fib[i] = fib[i-1] + fib[i-2];
            fib[i] %= mod;
        }
    }
    
    LL get ( LL a , LL b , int n )
    {
        if ( n == 1 ) return a%mod;
        if ( n == 2 ) return b%mod;
        return (a*fib[n-2]%mod+b*fib[n-1]%mod)%mod;
    }
    
    LL sum ( LL a , LL b , int n )
    {
        if ( n == 1 ) return a;
        if ( n == 2 ) return (a+b)%mod;
        return ((get ( a , b , n+2 )-b)%mod+mod)%mod;
    }
    
    void push_down ( int u )
    {
        int f1 = tree[u].f1;
        int f2 = tree[u].f2;
        int l = tree[u].l;
        int r = tree[u].r;
        int ll = (l+r)/2-l+1;
        int rr = r-(l+r)/2;
        if ( f1 )
        {
            if ( l != r )
            {
                tree[u<<1].f1 += f1;
                tree[u<<1].f1 %= mod;
                tree[u<<1].f2 += f2;
                tree[u<<1].f2 %= mod;
                tree[u<<1].sum += sum ( f1 , f2 , ll );
                tree[u<<1].sum %= mod;
                int x = f1 , y = f2;
                f2 = get ( x , y , ll+2 );
                f1 = get ( x , y , ll+1 );
                tree[u<<1|1].f2 += f2;
                tree[u<<1|1].f2 %= mod;
                tree[u<<1|1].f1 += f1;
                tree[u<<1|1].f1 %= mod;
                tree[u<<1|1].sum += sum ( f1 , f2 , rr );
                tree[u<<1|1].sum %= mod;
            }
            tree[u].f1 = tree[u].f2 = 0;
        }
    }
    
    void update ( int u , int left , int right )
    {
        int l = tree[u].l;
        int r = tree[u].r;
        int mid = l+r>>1;
        if ( left <= l && r <= right )
        {
            tree[u].f1 += fib[l-left+1];
            tree[u].f1 %= mod;
            tree[u].f2 += fib[l-left+2];
            tree[u].f2 %= mod;
            int f1 = fib[l-left+1], f2 = fib[l-left+2];
            tree[u].sum += sum ( f1 , f2 , r-l+1 );
            tree[u].sum %= mod;
            return;
        }
        push_down ( u);
        if ( left <= mid && right >= l )
            update ( u<<1 , left , right );
        if ( left <= r && right > mid )
            update ( u<<1|1 , left , right );
        push_up ( u );
    }
    
    LL query ( int u , int left , int right )
    {
        int l = tree[u].l;
        int r = tree[u].r;
        int mid = l+r>>1;
        if ( left <= l && r <= right )
            return tree[u].sum;
        push_down ( u );
        LL ret = 0;
        if ( left <= mid && right >= l ) 
        {
            ret += query ( u<<1 , left , right );
            ret %= mod;
        }
        if ( left <= r && right > mid )
        {
            ret += query ( u<<1|1 , left , right );
            ret %= mod;
        }
        return ret;
    }
    
    int main ( )
    {
        init ( );
        while ( ~scanf ( "%d%d" , &n , &m ) )
        {
            for ( int i = 1; i <= n ; i++ )
                scanf ( "%d" , &a[i] );
            build ( 1 , 1 , n );
            while ( m-- )
            {
                int x,l,r;
                scanf ( "%d%d%d" , &x , &l , &r );
                if ( x == 1 )
                    update ( 1 , l , r );
                else
                    printf ( "%lld
    " , query ( 1 , l , r ) );
            }
        }
    }
    

      

  • 相关阅读:
    devDependencies和dependencies的版本写法
    dependencies 与 devDependencies 的区别
    Java +selenium Navigation接口介绍
    Java + selenium window()接口方法介绍
    Java + selenium Timeout接口用法介绍
    Java + selenium 启动谷歌浏览器
    selenium 3 下载 + Java使用
    Rsync 实现服务器文件的同步——服务端的安装配置
    selenium V1.0和V2.0差别对比
    PHP的安装配置
  • 原文地址:https://www.cnblogs.com/boson-is-god/p/6178985.html
Copyright © 2011-2022 走看看