/*
充分利用了菲波那切数列的两条定理:
①定义F[1] = a, F[2] = b, F[n] = F[n - 1] + F[n - 2](n≥3)。
有F[n] = b * fib[n - 1] + a * fib[n - 2](n≥3),其中fib[i]为斐波那契数列的第 i 项。
②定义F[1] = a, F[2] = b, F[n] = F[n - 1] + F[n - 2](n≥3)。
有F[1] + F[2] + …… + F[n] = F[n + 2] - b
这题还有一个事实,就是两个上述定义的数列,相加,仍然符合F[n] = F[n - 1] + F[n - 2]的递推公式。
利用这两个定理,用线段树维护序列,线段树的每个结点记录这一段的前两项是什么,预处理好斐波那契数列
,便能O(1)地计算出每一个结点中间的数是多少、每一个结点的和。
充分利用了菲波那切数列的两条定理:
①定义F[1] = a, F[2] = b, F[n] = F[n - 1] + F[n - 2](n≥3)。
有F[n] = b * fib[n - 1] + a * fib[n - 2](n≥3),其中fib[i]为斐波那契数列的第 i 项。
②定义F[1] = a, F[2] = b, F[n] = F[n - 1] + F[n - 2](n≥3)。
有F[1] + F[2] + …… + F[n] = F[n + 2] - b
这题还有一个事实,就是两个上述定义的数列,相加,仍然符合F[n] = F[n - 1] + F[n - 2]的递推公式。
利用这两个定理,用线段树维护序列,线段树的每个结点记录这一段的前两项是什么,预处理好斐波那契数列
,便能O(1)地计算出每一个结点中间的数是多少、每一个结点的和。
*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
using namespace std;
#define maxn 300005
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ll long long
const ll mod=1000000009;
ll fibo[maxn],sum[maxn<<2],a[maxn<<2],b[maxn<<2];
//打表菲波那切数列
void get_fibo(){
fibo[1]=fibo[2]=1;
for(int i=3;i<maxn;i++)
fibo[i]=(fibo[i-1]+fibo[i-2])%mod;
}
//根据公式二得到该菲薄数列的第n个数
ll get_FB(int n,ll a1,ll b1){
if(n==1) return a1%mod;
else if(n==2) return b1%mod;
else return (b1*fibo[n-1]+a1*fibo[n-2])%mod;
}
void push_up(int rt){
sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%mod;
}
void push_down(int rt,int l,int r){
int mid=(l+r)>>1;
a[rt<<1]=(a[rt<<1]+a[rt])%mod;
b[rt<<1]=(b[rt]+b[rt<<1])%mod;
a[rt<<1|1]=(a[rt<<1|1]+get_FB(mid+1-l+1,a[rt],b[rt]))%mod;
b[rt<<1|1]=(b[rt<<1|1]+get_FB(mid+1-l+2,a[rt],b[rt]))%mod;
ll k1=(get_FB(mid-l+1+2,a[rt],b[rt])-b[rt]+mod)%mod; //记录前半部分的和
ll k2=(get_FB(r-l+1+2,a[rt],b[rt])-b[rt]-k1+mod)%mod; //记录后半部分的和
sum[rt<<1]=(sum[rt<<1]+k1)%mod;
sum[rt<<1|1]=(sum[rt<<1|1]+k2)%mod;
a[rt]=b[rt]=0;
}
void build(int l,int r,int rt){
a[rt]=b[rt]=0;
if(l==r){
scanf("%d",&sum[rt]); return;
}
int m=(l+r)>>1;
build(lson); build(rson);
push_up(rt);
}
void update(ll L,ll R,ll l,ll r,ll rt){
if(L<=l&&R>=r){
a[rt]=(a[rt]+fibo[l-L+1])%mod;
b[rt]=(b[rt]+fibo[l-L+2])%mod;
sum[rt]=(sum[rt]+get_FB(r-l+1+2,fibo[l-L+1],fibo[l-L+2])-fibo[l-L+2]+mod)%mod;
return;
}
push_down(rt,l,r);
ll m=(l+r)>>1;
if(L<=m) update(L,R,lson);
if(R>m) update(L,R,rson);
push_up(rt);
}
ll query(ll L,ll R,ll l,ll r,ll rt){
if(L<=l&&R>=r) return sum[rt]%mod;
push_down(rt,l,r);
ll m=(l+r)>>1; ll ret=0;
if(L<=m) ret+=query(L,R,lson);
if(R>m) ret+=query(L,R,rson);
return ret%mod;
}
int main(){
ll i,j,n,m,a1,b1,c1;
get_fibo();
cin>>n>>m;
build(1,n,1);
while(m--){
scanf("%lld%lld%lld",&a1,&b1,&c1);
if(a1==1) update(b1,c1,1,n,1);
else printf("%lld\n",(query(b1,c1,1,n,1)+mod)%mod);
}
return 0;
}