Codeforces 446C. DZY Loves Fibonacci Numbers【斐波那契+线段树】
C. DZY Loves Fibonacci Numbers
【题目描述】
【题解】
我们可以知道斐波那契数列有两个性质:
所以可以预先用矩阵乘法求出这个a和b,然后套线段树就可以了。
因为没模干净导致好几发WA,QAQ
【代码如下】
#include<cstdio>
using namespace std;
const int MAXN=300005,MOD=1e9+9;
int n,m,a[MAXN],Suma[MAXN],Tre[MAXN<<2];
void MO(int &x){x-=(x>=MOD?MOD:0);}
struct Matrix{
int a[2][2];
void INIT(){a[1][1]=a[1][0]=a[0][1]=1;a[0][0]=0;}
Matrix operator *(const Matrix b)const{
Matrix c;c.a[0][0]=c.a[1][0]=c.a[0][1]=c.a[1][1]=0;
for(int i=0;i<2;i++)for(int j=0;j<2;j++)for(int k=0;k<2;k++) c.a[i][j]=(1ll*c.a[i][j]+1ll*a[i][k]*b.a[k][j])%MOD;
return c;
}
}Mul[MAXN];
struct FIB{
int a[2];
int z(){return a[0];}
void clear(){a[0]=a[1]=0;}
FIB operator *(const Matrix b)const{
FIB c;c.a[0]=c.a[1]=0;
c.a[0]=(1ll*a[0]*b.a[0][0]+1ll*a[1]*b.a[0][1])%MOD,c.a[1]=(1ll*a[0]*b.a[1][0]+1ll*a[1]*b.a[1][1])%MOD;
return c;
}
FIB operator +(const FIB b)const{FIB c;MO(c.a[0]=a[0]+b.a[0]),MO(c.a[1]=a[1]+b.a[1]);return c;}
}Add[MAXN<<2];
FIB INIT(){FIB c;c.a[0]=0,c.a[1]=1;return c;}
int Sumfib(FIB f,int x){int z=(f*Mul[x+2]).z()-(f*Mul[2]).z();return z<0?z+MOD:z;}
int Sum(FIB x,int L,int R){int z=Sumfib(x,R)-Sumfib(x,L-1);return z<0?z+MOD:z;}
void PushDown(int rt,int L,int R){
int mid=(R+L)>>1;
MO(Tre[rt<<1]+=Sum(Add[rt],L-L+1,mid-L+1));Add[rt<<1]=Add[rt<<1]+Add[rt];
MO(Tre[rt<<1|1]+=Sum(Add[rt],mid+1-L+1,R-L+1));Add[rt<<1|1]=Add[rt<<1|1]+(Add[rt]*Mul[mid+1-L]);
Add[rt].clear();
}
void PushUp(int rt){MO(Tre[rt]=Tre[rt<<1]+Tre[rt<<1|1]);}
void Insert(int rt,int L,int R,int l,int r){
if(l<=L&&R<=r){MO(Tre[rt]+=Sum((FIB){0,1},L-l+1,R-l+1));Add[rt]=Add[rt]+(INIT()*Mul[L-l]);return;}
PushDown(rt,L,R);int mid=(R+L)>>1;
if(l<=mid) Insert(rt<<1,L,mid,l,r);if(r>mid) Insert(rt<<1|1,mid+1,R,l,r);PushUp(rt);
}
int Query(int rt,int L,int R,int l,int r){
if(l<=L&&R<=r) return Tre[rt];
PushDown(rt,L,R);int mid=(R+L)>>1,Ans=0;
if(l<=mid) MO(Ans+=Query(rt<<1,L,mid,l,r));if(r>mid) MO(Ans+=Query(rt<<1|1,mid+1,R,l,r));
return Ans;
}
int main(){
Mul[1].INIT();Mul[0].a[0][0]=Mul[0].a[1][1]=1;
for(int i=2;i<300005;i++) Mul[i]=Mul[i-1]*Mul[1];
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),MO(Suma[i]=Suma[i-1]+a[i]);
for(int i=1;i<=m;i++){
int Type,L,R;scanf("%d%d%d",&Type,&L,&R);
if(Type==1) Insert(1,1,n,L,R);else printf("%d\n",(Query(1,1,n,L,R)+(Suma[R]-Suma[L-1]+MOD)%MOD)%MOD);
}
return 0;
}