CF446C DZY Loves Fibonacci Numbers 题解

145 阅读2分钟

题目链接

思路

斐波那契数的一个性质:fibn+m=fibn+1fibm+fibnfibm1fib_{n+m}=fib_{n+1}fib_m+fib_nfib_{m-1},题目中对区间[L,R][L,R]操作时,位于pp的元素加了fibpL+1fib_{p-L+1},根据上述公式拆一下得到fibp+1fib1L+fibpfibLfib_{p+1}fib_{1-L}+fib_pfib_{-L},发现fibp+1fib_{p+1}fibpfib_p[L,R][L,R]无关,因此只维护下fib1Lfib_{1-L}fibLfib_{-L}的标记就可以了。

另外,斐波那契数列的通项公式:

fibn=15[(1+52)n(152)n]fib_n=\frac{1}{\sqrt 5}[(\frac{1+\sqrt5}{2})^n-(\frac{1-\sqrt 5}{2})^n]

代码

#include<bits/stdc++.h>
#define lc p<<1
#define rc p<<1|1
#define rep(i,st,ed) for(int i=st;i<=ed;++i)
#define bl(u,i) for(int i=head[u];i;i=e[i].nxt)
#define en puts("")
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll> 
typedef long long ll;
typedef double db;
using namespace std;
const ll INF=0x3f3f3f3f;
void read() {}
void OP() {}
void op() {}
template <typename T, typename... T2>
inline void read(T &_, T2 &... oth)
{
    int __=0;
    _=0;
    char ch=getchar();
    while(!isdigit(ch))
    {
        if(ch=='-')
            __=1;
        ch=getchar();
    }
    while(isdigit(ch))
    {
        _=_*10+ch-48;
        ch=getchar();
    }
    _=__?-_:_;
    read(oth...);
}
template <typename T>
void Out(T _)
{
    if(_<0)
    {
        putchar('-');
        _=-_;
    }
    if(_>=10)
       Out(_/10);
    putchar(_%10+'0');
}
template <typename T, typename... T2>
inline void OP(T _, T2... oth)
{
	Out(_);
	putchar('\n');
	OP(oth...);
}
template <typename T, typename... T2>
inline void op(T _, T2... oth)
{
	Out(_);
	putchar(' ');
	op(oth...);
}
/*#################################*/
const ll N=3E5+19,P=1E9+9;
ll n,m;
ll a[N],f[N],sf[N],neg[N],t[4*N],tag1[4*N],tag2[4*N];
void update(ll p)
{
	t[p]=(t[lc]+t[rc])%P;
}
void build(ll p,ll l,ll r)
{
	if(l==r)
	{
		t[p]=a[l];
		return;
	}
	ll mid=(l+r)>>1;
	build(lc,l,mid);
	build(rc,mid+1,r);
	update(p);
}
void flag(ll p,ll l,ll r,ll x,ll y)
{
	t[p]=(t[p]+(sf[r+1]-sf[l]+P)%P*x%P)%P;
	t[p]=(t[p]+(sf[r]-sf[l-1]+P)%P*y%P)%P;
	tag1[p]=(tag1[p]+x)%P;
	tag2[p]=(tag2[p]+y)%P;
}
void push_down(ll p,ll l,ll r)
{
	ll mid=(l+r)>>1;
	flag(lc,l,mid,tag1[p],tag2[p]);
	flag(rc,mid+1,r,tag1[p],tag2[p]);
	tag1[p]=tag2[p]=0;
}
void modify(ll p,ll l,ll r,ll al,ll ar)
{
	if(al<=l && ar>=r)
	{
		flag(p,l,r,neg[al-1],neg[al]);
		return;
	}
	if(tag1[p] || tag2[p])
		push_down(p,l,r);
	ll mid=(l+r)>>1;
	if(al<=mid)
		modify(lc,l,mid,al,ar);
	if(ar>mid)
		modify(rc,mid+1,r,al,ar);
	update(p);
}
ll query(ll p,ll l,ll r,ll al,ll ar)
{
	if(al<=l && ar>=r)
		return t[p];
	if(tag1[p] || tag2[p])
		push_down(p,l,r);
	ll mid=(l+r)>>1,ret=0;
	if(al<=mid)
		ret=(ret+query(lc,l,mid,al,ar))%P;
	if(ar>mid)
		ret=(ret+query(rc,mid+1,r,al,ar))%P;
	return ret;
}
void print()
{
	rep(i,1,4*n)
		OP(t[i]);
	en;
}
int main()
{
	read(n,m);
	rep(i,1,n)
		read(a[i]);
	f[1]=f[2]=1;
	neg[1]=1;
	rep(i,3,n+1)
		f[i]=(f[i-1]+f[i-2])%P;
	rep(i,2,n)
		neg[i]=i&1?f[i]:P-f[i];
	rep(i,1,n+1)
		sf[i]=(sf[i-1]+f[i])%P;
	build(1,1,n);
	ll ty,l,r;
	while(m--)
	{
		read(ty,l,r);
		if(ty==1)
			modify(1,1,n,l,r);
		else
			OP(query(1,1,n,l,r));
	}
}