Codeforces 446C. DZY Loves Fibonacci Numbers【斐波那契+线段树】

C. DZY Loves Fibonacci Numbers

【题目描述】

传送门

【题解】

我们可以知道斐波那契数列有两个性质:

i=1nFi=Fn+2F2\sum_{i=1}^{n} F_i=F_{n+2}-F_{2}

Fn=aF1+bF2F_n=aF_1+bF_2

所以可以预先用矩阵乘法求出这个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;
}
posted @ 2019-02-26 21:16  XSamsara  阅读(194)  评论(0编辑  收藏  举报