#include #include #define ll long long #define rep(i,l,r)for(ll i=(l);i<(r);i++) #define M 1000000007 //遅延セグ木ここから //↓ここを変える typedef struct sayouso{ll p,q,r;}sayouso; typedef struct atai{ll a,f;}atai; //↑ここを変える typedef struct node{sayouso T;atai x;}node; node lsegN[1<<21],*lseg; ll lsegNUM,lsegk; //↓ここから変える sayouso id={1,0,0}; atai xx(atai x,atai y){ atai ret; ret.a=(x.a+y.a)%M; ret.f=(x.f+y.f)%M; return ret; } atai Tx(sayouso T,atai x){ atai ret; ret.a=(T.p*x.a+T.q*x.f+T.r)%M; ret.f=x.f; return ret; } sayouso TT(sayouso S,sayouso T){ sayouso ret; ret.p=S.p*T.p%M; ret.q=(S.p*T.q+S.q)%M; ret.r=(S.p*T.r+S.r)%M; return ret; } sayouso fT(sayouso T,ll k){ sayouso ret; ret.p=T.p; ret.q=T.q; ret.r=(T.r<0;i--)lsegN[i].x=xx(lsegN[2*i].x,lsegN[2*i+1].x); rep(i,1,2*lsegNUM)lsegN[i].T=id; } void lsegupdatesub(ll l,ll r,sayouso T,ll i,ll cl,ll cr,ll ck){ //disjointなとき if(cr<=l||r<=cl)return; //完全に含むとき if(l<=cl&&cr<=r){ lsegN[i].T=TT(T,lsegN[i].T); return; } //どちらでもないとき //遅延伝播 lsegN[2*i ].T=TT(lsegN[i].T,lsegN[2*i ].T); lsegN[2*i+1].T=TT(lsegN[i].T,lsegN[2*i+1].T); //再帰的に更新 ll cm=(cl+cr)/2; lsegupdatesub(l,r,T,2*i ,cl,cm,ck-1); lsegupdatesub(l,r,T,2*i+1,cm,cr,ck-1); //自身のnodeを更新 lsegN[i].x=xx(Tx(fT(lsegN[2*i].T,ck-1),lsegN[2*i].x),Tx(fT(lsegN[2*i+1].T,ck-1),lsegN[2*i+1].x)); lsegN[i].T=id; } void lsegupdate(ll l,ll r,sayouso T){lsegupdatesub(l,r,T,1,0,lsegNUM,lsegk);} atai lsegcalcsub(ll l,ll r,ll i,ll cl,ll cr,ll ck){ //完全に含むとき if(l<=cl&&cr<=r)return Tx(fT(lsegN[i].T,ck),lsegN[i].x); ll cm=(cl+cr)/2; //遅延伝播(変更はないので配るだけで良い) lsegN[2*i ].T=TT(lsegN[i].T,lsegN[2*i ].T); lsegN[2*i+1].T=TT(lsegN[i].T,lsegN[2*i+1].T); lsegN[i].x=Tx(fT(lsegN[i].T,ck),lsegN[i].x); lsegN[i].T=id; //左側だけ if(r<=cm)return lsegcalcsub(l,r,2*i ,cl,cm,ck-1); //右側だけ if(cm<=l)return lsegcalcsub(l,r,2*i+1,cm,cr,ck-1); //両方 return xx(lsegcalcsub(l,r,2*i,cl,cm,ck-1),lsegcalcsub(l,r,2*i+1,cm,cr,ck-1)); } atai lsegcalc(ll l,ll r){return lsegcalcsub(l,r,1,0,lsegNUM,lsegk);} //遅延セグ木ここまで int main(){ int Q; scanf("%*d%d",&Q); lseguse(1<<20); lseg[1].x.f=1; rep(i,2,1000010)lseg[i].x.f=(lseg[i-1].x.f+lseg[i-2].x.f)%M; lseginit(); while(Q--){ int q,l,r,k; sayouso T; scanf("%d%d%d%d",&q,&l,&r,&k); r++; if(q==0)printf("%lld\n",lsegcalc(l,r).a); else if(q==1){ T.p=0,T.q=0,T.r=k; lsegupdate(l,r,T); }else if(q==2){ T.p=1,T.q=0,T.r=k; lsegupdate(l,r,T); }else if(q==3){ T.p=k,T.q=0,T.r=0; lsegupdate(l,r,T); }else if(q==4){ T.p=1,T.q=k,T.r=0; lsegupdate(l,r,T); } } return 0; }