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 integers a1, 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.
题意:有n个数,每一次操作可能是在下标为[l,r]的数对应加上f[1],f[2],f[3]....f[r-l+1],一个操作是询问[l,r]的数的和是多少。
思路:首先发现mod=1e9+9. 那么在该系下5是二次剩余。这样我们能把sqrt(5)换成一个整数来运算。由于斐波那契数列是两个等比数列组合而成的。所以那个第一个操作就是相当于在[l,r]上对应加上一个等比数列。 我们在线段树的每个节点只要存等比数列的首项就行了,因为线段树的每个节点的长度是固定的,所以加上一段等比数列 就是 + a0(1-q^n)/(1-q) 这里面除了a0不是固定的,其他是固定的。这样基本思路就有了。感觉边界条件讨论起来很吃力,难道真的是老了吗?
代码:
#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <string.h>
#include <string>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
using namespace std;
#define mp make_pair
#define rep(i,n) for(int i=0;i<n;++i)
#define clr(a,x) memset(a,x,sizeof(a))
#define LL long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int N=300000+5;
const int mod=1e9+9;
const LL sqr=383008016;
LL sum[N<<2],col[N<<2][2];
LL a[N],b[N],F[N],c;
LL Sa[N],Sb[N];
LL qpow(LL base,LL p)
{
LL ret=1;
while(p>0) {
if(p&1) ret=(ret*base)%mod;
base=(base*base)%mod;
p>>=1;
}
return ret;
}
void pushdown(int l,int r,int m,int rt)
{
int ls=rt<<1,rs=rt<<1|1;
if(col[rt][0]) {
col[ls][0]+=col[rt][0]; col[rs][0]+=(col[rt][0]*a[m+1-l])%mod;
col[ls][0]%=mod; col[rs][0]%=mod;
sum[ls]+= ((c*col[rt][0])%mod*Sa[m-l])%mod;
sum[rs]+=(((((c*col[rt][0])%mod)*a[m+1-l])%mod)*Sa[r-m-1])%mod;
}
if(col[rt][1]) {
col[ls][1]+=col[rt][1]; col[rs][1]+=(col[rt][1]*b[m-l+1])%mod;
col[ls][1]%=mod; col[rs][1]%=mod;
sum[ls] -= ((c*col[rt][1])%mod*Sb[m-l])%mod;
sum[rs] -=(((((c*col[rt][1])%mod)*b[m+1-l])%mod)*Sb[r-m-1])%mod;
}
sum[ls]%=mod; sum[rs]%=mod;
if(sum[ls]<0) sum[ls]+=mod;
if(sum[rs]<0) sum[rs]+=mod;
col[rt][0]=col[rt][1]=0;
}
inline void pushup(int rt) { sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%mod; }
void update1(int p,int x,int l,int r,int rt)
{
if(l==r) { sum[rt]+=x; return; }
int m=(l+r)>>1;
if(p<=m) update1(p,x,lson);
else update1(p,x,rson);
pushup(rt);
}
void update2(int L,int R,int k,int l,int r,int rt)
{
if(L==l&&r==R) {
col[rt][0]=(col[rt][0]+a[k])%mod;
col[rt][1]=(col[rt][1]+b[k])%mod;
sum[rt]=(sum[rt]+F[k+r-l]-F[k-1])%mod;
if(sum[rt]<0) sum[rt]+=mod;
return;
}
int m=(l+r)>>1;
pushdown(l,r,m,rt);
if(R<=m) update2(L,R,k,lson);
else if(L>m) update2(L,R,k,rson);
else {
update2(L,m,k,lson);
update2(m+1,R,k+m-L+1,rson);
}
pushup(rt);
}
LL query(int L,int R,int l,int r,int rt)
{
if (L<=l&&r<=R) return sum[rt];
int m=(l+r)>>1;
LL ret=0;
pushdown(l,r,m,rt);
if(L<=m) ret+=query(L,R,lson);
if(m<R) ret+=query(L,R,rson);
pushup(rt);
return ret%mod;
}
void pre_init()
{
c=qpow(sqr,mod-2);
F[1]=F[2]=1;
for(int i=3;i<N;++i) F[i]=(F[i-1]+F[i-2])%mod;
for(int i=2;i<N;++i) F[i]=(F[i-1]+F[i])%mod;
LL x=((1+sqr)*qpow(2,mod-2))%mod;
a[0]=1;
for(int i=1;i<N;++i) a[i]=(a[i-1]*x)%mod;
x=((1-sqr)*qpow(2,mod-2))%mod;
if(x<0) x+=mod;
b[0]=1;
for(int i=1;i<N;++i) b[i]=(b[i-1]*x)%mod;
Sa[0]=Sb[0]=1;
for(int i=1;i<N;++i) Sa[i]=(Sa[i-1]+a[i])%mod;
for(int i=1;i<N;++i) Sb[i]=(Sb[i-1]+b[i])%mod;
}
int main()
{
pre_init();
int n,q;
cin>>n>>q;
for(int i=1;i<=n;++i) {
int x; scanf("%d",&x);
update1(i,x,1,n,1);
}
while(q--){
int o,l,r; scanf("%d%d%d",&o,&l,&r);
if(o==2) printf("%I64d\n",query(l,r,1,n,1));
else update2(l,r,1,1,n,1);
}
}