题意,给定一个数列,区间更新,每次加上对应的fibnacci值。
思路,要用到两个定理:
假设正常的fibnacci值为fib[i](指以1 1为开头的数列),则以a,b开头的数列的第k个数为a * fib[k-2] + b * fib[k-1];
以a,b开头的k个数之和为fib[k+2] - fib[2](此处为b)
下面是代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <functional>
#include <sstream>
#include <iomanip>
#include <cmath>
#include <cstdlib>
#include <ctime>
//#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
#define INF 1e9
#define MAXN 21
#define maxn 300005
#define mod 1000000009
#define eps 1e-7
#define pi 3.1415926535897932384626433
#define rep(i,n) for(int i=0;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define scan(n) scanf("%d",&n)
#define scanll(n) scanf("%I64d",&n)
#define scan2(n,m) scanf("%d%d",&n,&m)
#define scans(s) scanf("%s",s);
#define ini(a) memset(a,0,sizeof(a))
#define out(n) printf("%d\n",n)
ll gcd(ll a,ll b) {return b==0?a:gcd(b,a%b);}
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
ll add1[maxn<<2],add2[maxn<<2];
ll fib[maxn];ll sum[maxn<<2];
int n,m;
void init()
{
fib[0] = 0;
fib[1] = 1;
for(int i = 2;i < maxn; i++) fib[i] = (fib[i-1] + fib[i-2]) % mod;
}
ll getFib(ll a,ll b,int k) //求以a,b开头的第k个数
{
if(k == 1) return a;
if(k == 2) return b;
return (a * fib[k-2] + b * fib[k-1]) % mod;
}
ll getFibsum(ll a,ll b,int k) //以a,b开头的k个数之和
{
if(k == 1) return a;
if(k == 2) return a + b;
return (getFib(a, b, k+2) - b + mod) % mod;
}
void PushUp(int rt) {
sum[rt] = (sum[rt<<1] + sum[rt<<1|1]) % mod;
}
void build(int l,int r,int rt) {
add1[rt] = 0;
add2[rt] = 0;
if (l == r) {
scanf("%I64d",&sum[rt]);
return ;
}
int m = (l + r) >> 1;
build(lson);
build(rson);
PushUp(rt);
}
void add(ll a,ll b,int l,int r,int rt)
{
sum[rt] = (sum[rt] + getFibsum(a,b,r-l+1)) % mod;
add1[rt] = (add1[rt] + a) % mod;
add2[rt] = (add2[rt] + b) % mod;
}
void PushDown(int l,int r,int rt) {
if(add1[rt] || add2[rt]){
int m = (l + r) >> 1;
add(add1[rt],add2[rt],lson);
add(getFib(add1[rt],add2[rt],m+1-l+1),getFib(add1[rt],add2[rt],m+2-l+1),rson);
add1[rt] = add2[rt] = 0;
}
}
void update(int L,int R,int l,int r,int rt) {
if (L <= l && r <= R) {
add(fib[l-L+1],fib[l-L+2],l,r,rt);
return ;
}
PushDown(l , r , rt);
int m = (l + r) >> 1;
if (L <= m) update(L , R , lson);
if (m < R) update(L , R, rson);
PushUp(rt);
}
ll query(int L,int R,int l,int r,int rt) {
if (L <= l && r <= R) {
return sum[rt];
}
PushDown( l , r , rt);
int m = (l + r) >> 1;
ll ret = 0;
if (L <= m) ret = (ret + query(L , R , lson)) % mod;
if (m < R) ret = (ret + query(L , R , rson)) % mod;
return ret;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
#endif
init();
while(~scanf("%d%d",&n,&m))
{
build(1,n,1);
int ty,L,R;
while(m--)
{
// cout<<"aaa: "<<query(4,4,1,n,1)<<"bbb: "<<query(5,5,1,n,1)<<endl;
scanf("%d%d%d",&ty,&L,&R);
if(ty == 1) update(L,R,1,n,1);
else
{
printf("%I64d\n",query(L,R,1,n,1));
}
}
}
return 0;
}