Codeforces 446C DZY Loves Fibonacci Numbers [线段树,数论]
思路
这题知道结论就是水题,不知道就是神仙题……
斐波那契数有这样一个性质:\(f_{n+m}=f_{n+1}f_m+f_{n}f_{m-1}\)。
至于怎么证明嘛……
即得易见平凡,仿照上例显然。留作习题答案略,读者自证不难。
反之亦然同理,推论自然成立,略去过程QED,由上可知证毕。
其实就是我不会
而且这个性质对于负数下标也是成立的。
负数下标的斐波那契数怎么求?你从\(f_{-1}+f_0=f_1\)可以得到\(f_{-1}=1\),后面的你也倒推回去就可以了,最后得到\(f_{-i}=(-1)^{i+1}f_i,i\geq 0\)。
回到本题。在一次\([l,r]\)的修改操作中,位置\(x\in[l,r]\)所加的值为\(f_{x-l+1}=f_{x+1}f_{1-l}+f_xf_{-l}\)
你发现可以用线段树维护,随便写写就过了。我才不告诉你我数组开小、没取模拼命WA呢。
代码
#include<bits/stdc++.h>
namespace my_std{
using namespace std;
#define pii pair<int,int>
#define fir first
#define sec second
#define MP make_pair
#define rep(i,x,y) for (int i=(x);i<=(y);i++)
#define drep(i,x,y) for (int i=(x);i>=(y);i--)
#define go(x) for (int i=head[x];i;i=edge[i].nxt)
#define sz 303030
typedef long long ll;
const ll mod=1e9+9;
template<typename T>
inline void read(T& t)
{
t=0;char f=0,ch=getchar();
double d=0.1;
while(ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar();
while(ch<='9'&&ch>='0') t=t*10+ch-48,ch=getchar();
if(ch=='.')
{
ch=getchar();
while(ch<='9'&&ch>='0') t+=d*(ch^48),d*=0.1,ch=getchar();
}
t=(f?-t:t);
}
template<typename T,typename... Args>
inline void read(T& t,Args&... args){read(t); read(args...);}
void file()
{
#ifndef ONLINE_JUDGE
freopen("a.txt","r",stdin);
#endif
}
// inline ll mul(ll a,ll b){ll d=(ll)(a*(double)b/mod+0.5);ll ret=a*b-d*mod;if (ret<0) ret+=mod;return ret;}
}
using namespace my_std;
int n,m;
int a[sz];
ll f[sz],ff[sz],F[sz];
void init()
{
F[1]=f[1]=1;
rep(i,2,sz-1) F[i]=(F[i-1]+(f[i]=(f[i-1]+f[i-2])%mod))%mod;
rep(i,1,sz-1) ff[i]=(i&1)?f[i]:mod-f[i];
}
ll tg1[sz<<2],tg2[sz<<2],sum[sz<<2];
#define ls k<<1
#define rs k<<1|1
#define lson k<<1,l,mid
#define rson k<<1|1,mid+1,r
#define S int k,int l,int r
#define I inline
I void Add1(S,ll s){(tg1[k]+=s)%=mod;(sum[k]+=s*(F[r]-F[l-1]+mod)%mod)%=mod;}
I void Add2(S,ll s){(tg2[k]+=s)%=mod;(sum[k]+=s*(F[r+1]-F[l]+mod)%mod)%=mod;}
I void pushdown(S)
{
if (!tg1[k]&&!tg2[k]) return;
int mid=(l+r)>>1;
ll &t1=tg1[k],&t2=tg2[k];
Add1(lson,t1);Add1(rson,t1);
Add2(lson,t2);Add2(rson,t2);
t1=t2=0;
}
void pushup(int k){sum[k]=(sum[ls]+sum[rs])%mod;}
void add(S,int x,int y,ll s1,ll s2)
{
if (x<=l&&r<=y) return Add1(k,l,r,s1),Add2(k,l,r,s2);
pushdown(k,l,r);
int mid=(l+r)>>1;
if (x<=mid) add(lson,x,y,s1,s2);
if (y>mid) add(rson,x,y,s1,s2);
pushup(k);
}
ll query(S,int x,int y)
{
if (x<=l&&r<=y) return sum[k];
pushdown(k,l,r);
int mid=(l+r)>>1;
ll ret=0;
if (x<=mid) ret+=query(lson,x,y);
if (y>mid) ret+=query(rson,x,y);
return ret%mod;
}
void build(S)
{
if (l==r) return (void)(sum[k]=a[l]%mod);
int mid=(l+r)>>1;
build(lson);build(rson);
pushup(k);
}
int main()
{
file();
int x,y,z;
read(n,m);
rep(i,1,n) read(a[i]);
init();
build(1,1,n);
while (m--)
{
read(z,x,y);
if (z==1) add(1,1,n,x,y,ff[x],ff[x-1]);
else printf("%lld\n",query(1,1,n,x,y));
}
return 0;
}