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

    Description:

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

    Hint:

    (n le 3*10^5)

    Solution:

    数据结构结合数学

    首先有公式 (sum _{i=1}^n fib(i)=fib(n+2))

    且由于斐波那契的递推是线性的,故所有的(fib(i))都可以表示成(a*fib(1)+b*fib(2))的形式

    考虑用线段树维护一个区间前两个位置的系数,然后就可以做了

    #include <map>
    #include <set>
    #include <stack>
    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #define ls p<<1 
    #define rs p<<1|1
    using namespace std;
    typedef long long ll;
    const ll mxn=1e6+5,mod=1e9+9;
    ll n,m,cnt,a[mxn],hd[mxn];
    ll f[mxn],tr[mxn<<2],vis[mxn<<2],tag[mxn<<2][2];
    
    inline ll read() {
    	char c=getchar(); ll x=0,f=1;
    	while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
    	while(c<='9'&&c>='0') {x=(x<<3)+(x<<1)+(c&15);c=getchar();}
    	return x*f;
    }
    inline void chkmax(ll &x,ll y) {if(x<y) x=y;}
    inline void chkmin(ll &x,ll y) {if(x>y) x=y;}
    
    struct ed {
    	ll to,nxt;
    }t[mxn<<1];
    
    inline void add(ll u,ll v) {
    	t[++cnt]=(ed) {v,hd[u]}; hd[u]=cnt;
    }
    
    void push_up(ll p) {
    	tr[p]=(tr[ls]+tr[rs])%mod;
    }
    
    struct ST {
    	ll x,y;
    };
    
    ST fibget(ST tp,ll len) {
    	ll c=tp.x*f[len]%mod+tp.y*f[len+1]%mod,d=tp.x*f[len+1]%mod+tp.y*f[len+2]%mod;
    	return (ST) {c%mod,d%mod};
    }
    
    ll fibcal(ll f1,ll f2,ll len) {
    	ll res=0;
    	if(len>=1) res=f1;
    	if(len>=2) res=(res+f2)%mod;
    	if(len>=3) res=(res+f2*(f[len+1]-2)%mod+f1*(f[len]-1)%mod+mod)%mod;
    	//前两项的系数的值,直接乘以当前f[i+1],f[i],计算出f[i+2]
    	return res;
    }
    
    void push_down(ll p,ll l,ll r) {
    	ll mid=(l+r)>>1;
    	if(vis[p]) {
    		ll &a=tag[p][0],&b=tag[p][1];
    		tag[ls][0]=(tag[ls][0]+a)%mod;
    		tag[ls][1]=(tag[ls][1]+b)%mod;
    		tr[ls]=(tr[ls]+fibcal(a,b,mid-l+1))%mod;
    		vis[ls]=1;
    
    		ll c=a*f[mid-l]+b*f[mid-l+1],d=a*f[mid-l+1]+b*f[mid-l+2];
    		c%=mod; d%=mod;
    		tag[rs][0]=(tag[rs][0]+c)%mod;
    		tag[rs][1]=(tag[rs][1]+d)%mod;
    		tr[rs]=(tr[rs]+fibcal(c,d,r-mid))%mod;
    		vis[rs]=1;
    		
    		vis[p]=tag[p][0]=tag[p][1]=0;
    	}
    }
    
    void build(ll l,ll r,ll p) {
    	if(l==r) {tr[p]=a[l]; return ;}
    	ll mid=(l+r)>>1;
    	build(l,mid,ls); build(mid+1,r,rs); push_up(p);
    }
    
    void modify(ll l,ll r,ll ql,ll qr,ll val1,ll val2,ll p) {
    	if(ql<=l&&r<=qr) {
    		tag[p][0]=(tag[p][0]+val1)%mod;
    		tag[p][1]=(tag[p][1]+val2)%mod;
    		tr[p]=(tr[p]+fibcal(val1,val2,r-l+1))%mod;
    		vis[p]=1; return ;
    	}
    	ll mid=(l+r)>>1; push_down(p,l,r);
    	if(qr<=mid) modify(l,mid,ql,qr,val1,val2,ls);
    	else if(ql>mid) modify(mid+1,r,ql,qr,val1,val2,rs);
    	else {
    		modify(l,mid,ql,qr,val1,val2,ls);
    		ST z=fibget((ST){val1,val2},mid-ql);
    		modify(mid+1,r,mid+1/*询问区间也要更改*/,qr,z.x,z.y,rs); //算出区间前两个fib,貌似也可以用前缀和
    	}
    	push_up(p);
    }
    
    ll query(ll l,ll r,ll ql,ll qr,ll p) {
    	if(ql<=l&&r<=qr) return tr[p];
    	ll mid=(l+r)>>1; push_down(p,l,r); ll res=0;
    	if(ql<=mid) res=(res+query(l,mid,ql,qr,ls))%mod;
    	if(qr>mid) res=(res+query(mid+1,r,ql,qr,rs))%mod;
    	return res;
    }
    
    void init() {
    	n=read(); m=read(); ll x,y,opt; f[1]=f[2]=1; 
    	for(ll i=3;i<=n+4;++i) f[i]=(f[i-1]+f[i-2])%mod;
    	for(ll i=1;i<=n;++i) a[i]=read()%mod; build(1,n,1);
    	for(ll i=1;i<=m;++i) {
    		opt=read(); x=read(); y=read();
    		if(opt==1) modify(1,n,x,y,1,1,1);
    		else printf("%lld
    ",(query(1,n,x,y,1)+mod)%mod);
    	}
    }
    
    int main()
    {
    	init();
        return 0;
    }
    
    
  • 相关阅读:
    mysql 数据库初识
    Python3进行RSA2加密、解密、签名
    jenkins一次构建两次触发job问题
    docker 端口被占用问题解决
    jacoco 的使用及与jenkins的集成
    python 学习笔记二 (列表推导式)
    python 学习笔记一 (数据结构和算法)
    请求超时及重试的设置
    python 中 str与bytes的转换
    JS模块化
  • 原文地址:https://www.cnblogs.com/list1/p/10569701.html
Copyright © 2011-2022 走看看