/*
感叹自己的代码能力实在是很差.
非常不错的题目
给定一列数,定义操作: 从一段数从头开始逐次加上f1,f2,f3,...,f(r-l+1).
利用线段树解决.
首先将连续的Fibonacci数通项公式转化为离散化的,利用二次剩余以及乘法逆元.
那么,对于一个区间的加和操作可以理解为对一个区间几何级数系数的维护.
这个可以利用线段树轻松解决.
*/
#include <cstdio>
#include <cstring>
#include <cmath>
#define LL long long
const int maxn = 300000 + 100;
const LL inv = 276601605;
const LL q1 = 691504013;
const LL q2 = 308495997;
const LL MOD = 1e9 + 9;
LL sum[maxn<<2];
LL p1[maxn<<2];
LL p2[maxn<<2];
LL pw1[maxn],pw2[maxn];
LL f1[maxn],f2[maxn];
LL a[maxn];
int tl,tr;
void init()
{
pw1[0]=1,pw2[0]=1;
for(int i=1;i<=300000+100;i++)
{
pw1[i]=(pw1[i-1]*q1)%MOD;
pw2[i]=(pw2[i-1]*q2)%MOD;
}
f1[1]=1,f2[1]=1;
for(int i=2;i<=300000+100;i++)
{
f1[i]=(f1[i-1]+pw1[i-1])%MOD;
f2[i]=(f2[i-1]+pw2[i-1])%MOD;
}
}
void pushdown(int l,int r,int rt)
{
if(l==r)
return;
int mid = (l+r)>>1;
int lc = rt<<1;
int rc = rt<<1|1;
LL delta;
if(p1[rt]!=0)
{
p1[lc]=(p1[lc]+p1[rt])%MOD;
sum[lc]=(sum[lc]+(p1[rt]*f1[mid-l+1]%MOD)+MOD)%MOD;
delta=(p1[rt]*pw1[mid-l+1])%MOD;
p1[rc]=(p1[rc]+delta+MOD)%MOD;
sum[rc]=(sum[rc]+(delta*f1[r-mid])%MOD+MOD)%MOD;
p1[rt]=0;
}
if(p2[rt]!=0)
{
p2[lc]=(p2[lc]+p2[rt])%MOD;
sum[lc]=(sum[lc]-(p2[rt]*f2[mid-l+1]%MOD)+MOD)%MOD;
delta=(p2[rt]*pw2[mid-l+1])%MOD;
p2[rc]=(p2[rc]+delta+MOD)%MOD;
sum[rc]=(sum[rc]-(delta*f2[r-mid])%MOD+MOD)%MOD;
p2[rt]=0;
}
}
void update(int l,int r,int rt)
{
pushdown(l,r,rt);
if(tl<=l&&r<=tr)
{
LL delta=pw1[l-tl+1];
p1[rt]=(p1[rt]+delta)%MOD;
sum[rt]=(sum[rt]+delta*f1[r-l+1]%MOD+MOD)%MOD;
delta=pw2[l-tl+1];
p2[rt]=(p2[rt]+delta)%MOD;
sum[rt]=(sum[rt]-delta*f2[r-l+1]%MOD+MOD)%MOD;
}
else
{
int mid=(l+r)>>1;
if(tl<=mid) update(l,mid,rt<<1);
if(tr>mid) update(mid+1,r,rt<<1|1);
sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%MOD;
}
}
LL query(int L,int R,int l,int r,int rt)
{
pushdown(l,r,rt);
if(L<=l&&r<=R)
{
return sum[rt];
}
int mid=(l+r)>>1;
if(R<=mid) return query(L,R,l,mid,rt<<1);
if(L>mid) return query(L,R,mid+1,r,rt<<1|1);
return (query(L,R,l,mid,rt<<1)+query(L,R,mid+1,r,rt<<1|1))%MOD;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
a[i]=(a[i-1]+a[i])%MOD;
}
init();
while(m--)
{
int op;
scanf("%d%d%d",&op,&tl,&tr);
if(op==1)
{
update(1,n,1);
}
else
{
LL ans=query(tl,tr,1,n,1);
ans=(ans*inv)%MOD;
ans=(ans+a[tr]-a[tl-1]+2*MOD)%MOD;
if(ans<0) ans=(ans+MOD)%MOD;
printf("%lld\n",ans);
}
}
return 0;
}
446 C. DZY Loves Fibonacci Numbers
最新推荐文章于 2019-06-19 13:52:09 发布