In mathematical terms, the sequence Fn of Fibonacci numbers is defined by the recurrence relation
DZY loves Fibonacci numbers very much. Today DZY gives you an array consisting of n integers: a1, a2, ..., an. Moreover, there are mqueries, each query has one of the two types:
- Format of the query "1 l r". In reply to the query, you need to add Fi - l + 1 to each element ai, where l ≤ i ≤ r.
- Format of the query "2 l r". In reply to the query you should output the value of modulo 1000000009 (109 + 9).
Help DZY reply to all the queries.
The first line of the input contains two integers n and m (1 ≤ n, m ≤ 300000). The second line contains n integersa1, a2, ..., an (1 ≤ ai ≤ 109) — initial array a.
Then, m lines follow. A single line describes a single query in the format given in the statement. It is guaranteed that for each query inequality 1 ≤ l ≤ r ≤ n holds.
For each query of the second type, print the value of the sum on a single line.
4 4 1 2 3 4 1 1 4 2 1 4 1 2 4 2 1 3
17 12
After the first query, a = [2, 3, 5, 7].
For the second query, sum = 2 + 3 + 5 + 7 = 17.
After the third query, a = [2, 4, 6, 9].
For the fourth query, sum = 2 + 4 + 6 = 12.
利用斐波那契数列的两个性质,若一个数列满足F(1)=a,F(2)=b,F(i)=F(i-2)+F(i-1),则有F(n)=a*Fib(n-2)+b*Fib(n-1),且F的前N项和等于F(n+2)-F(2)。
先预处理出斐波那契数列的前n+2项。
区间操作相当于对一个区间加上一个一一对应的区间,我们可以利用上面的两条性质,用F(n+2)=a*fib(n)+b*fib(n+1)求出F(n+2),再利用F(n+2)-F(2)求出加给当前区间的总值,更新区间和数组。
我们发现对于一个区间我们需要维护第一项和第二项的值,因为每次加的数列都满足F(n)=F(n-1)+F(n-2)的性质,所以可以将首项和第二项相加,再用公式直接计算区间和。
在下放标记的时候,左子树直接加父亲的首项和第二项的标记即可,右子树需要计算父亲的F(mid+1-l+1),F(mid+2-l+1)再累加上去。
<span style="font-size:18px;">#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 1200003
#define p 1000000009
#define LL long long
using namespace std;
int n,m;
LL delta[N],delta1[N],a[N],b[N],tr[N],f[N],val[N],sum[N];
void update(int now)
{
tr[now]=tr[now<<1]+tr[now<<1|1];
}
void build(int now,int l,int r)
{
if (l==r)
{
tr[now]=val[l];
return;
}
int mid=(l+r)/2;
build(now<<1,l,mid);
build(now<<1|1,mid+1,r);
tr[now]=tr[now<<1]+tr[now<<1|1];
}
LL F(int x,LL a,LL b)
{
return (a%p*f[x-2]%p+b%p*f[x-1]%p)%p;
}
LL calc(LL a,LL b,int x)
{
return ((F(x+2,a,b)-b%p)%p+p)%p;
}
LL solve(LL a,LL b,LL x)
{
return (a%p*f[x-2]%p+b%p*f[x-1]%p)%p;
}
void pushdown(int now,int l,int r)
{
int mid=(l+r)/2;
if (a[now]||b[now])
{
a[now<<1]=(a[now<<1]+a[now])%p; b[now<<1]=(b[now<<1]+b[now])%p;
if (mid-l+1==1) b[now<<1]=0;
tr[now<<1]+=calc(a[now],b[now],mid-l+1)%p; tr[now<<1]%=p;
LL t=solve(a[now],b[now],mid+1-l+1)%p;
LL t1=solve(a[now],b[now],mid+2-l+1)%p;
a[now<<1|1]=(a[now<<1|1]+t)%p;
b[now<<1|1]=(b[now<<1|1]+t1)%p;
if (r-mid==1) t1=0;
tr[now<<1|1]+=calc(t,t1,r-mid); tr[now<<1|1]%=p;
a[now]=0; b[now]=0;
}
}
void qjchange(int now,int l,int r,int ll,int rr)
{
if (ll<=l&&r<=rr)
{
a[now]=(a[now]+f[l-ll+1])%p; b[now]=(b[now]+f[l-ll+2])%p;
LL t=f[l-ll+1]%p; LL t1=f[l-ll+2]%p;
if (r-l+1==1) t1=0;
tr[now]=(tr[now]+calc(t,t1,r-l+1))%p;// cout<<now<<" "<<l<<" "<<r<<" "<<tr[now]<<endl;
return;
}
int mid=(l+r)/2;
pushdown(now,l,r);
if (ll<=mid) qjchange(now<<1,l,mid,ll,rr);
if (rr>mid) qjchange(now<<1|1,mid+1,r,ll,rr);
update(now);
}
LL qjsum(int now,int l,int r,int ll,int rr)
{
if (ll<=l&&r<=rr) return tr[now]%p;
int mid=(l+r)/2;
pushdown(now,l,r);
LL ans=0;
if (ll<=mid) ans=(ans+qjsum(now<<1,l,mid,ll,rr))%p;
if (rr>mid) ans=(ans+qjsum(now<<1|1,mid+1,r,ll,rr))%p;
return ans%p;
}
int main()
{
//freopen("a.in","r",stdin);
//freopen("my.out","w",stdout);
scanf("%d%d",&n,&m);
f[1]=1; f[2]=1;
for (int i=3;i<=n+10;i++) f[i]=(f[i-1]+f[i-2])%p;
for (int i=1;i<=n;i++) scanf("%d",&val[i]);
build(1,1,n);
for (int i=1;i<=m;i++)
{
int opt,x,y; scanf("%d%d%d",&opt,&x,&y);
if (opt==1) qjchange(1,1,n,x,y);
else printf("%I64d\n",qjsum(1,1,n,x,y)%p);
}
}</span>