直接下放矩阵即可。有点卡常,矩阵乘法一定要直接暴力写,不要for。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<ctime> #define maxn 100050 #define mod 1000000007 using namespace std; int n,m,root,tot=0,type,x,y,z,ls[maxn<<2],rs[maxn<<2]; struct matrix { int a[3][3]; }val[maxn<<2],lazy[maxn<<2],base[50],F; int read() { char ch;int data=0; while (ch<'0' || ch>'9') ch=getchar(); while (ch>='0' && ch<='9') { data=data*10+ch-'0'; ch=getchar(); } return data; } matrix mul(matrix a,matrix b) { matrix c; c.a[1][1]=(1LL*a.a[1][1]*b.a[1][1]+1LL*a.a[1][2]*b.a[2][1])%mod; c.a[1][2]=(1LL*a.a[1][1]*b.a[1][2]+1LL*a.a[1][2]*b.a[2][2])%mod; c.a[2][1]=(1LL*a.a[2][1]*b.a[1][1]+1LL*a.a[2][2]*b.a[2][1])%mod; c.a[2][2]=(1LL*a.a[2][1]*b.a[1][2]+1LL*a.a[2][2]*b.a[2][2])%mod; return c; } matrix f_pow(int x) { matrix ans=F;int ret=0; while (x) { if (x&1) ans=mul(ans,base[ret]); x>>=1;ret++; } return ans; } matrix add(matrix a,matrix b) { matrix c; c.a[1][1]=(a.a[1][1]+b.a[1][1])%mod; c.a[1][2]=(a.a[1][2]+b.a[1][2])%mod; c.a[2][1]=(a.a[2][1]+b.a[2][1])%mod; c.a[2][2]=(a.a[2][2]+b.a[2][2])%mod; return c; } void pushdown(int now,int left,int right) { if (left==right) return; lazy[ls[now]]=mul(lazy[ls[now]],lazy[now]); lazy[rs[now]]=mul(lazy[rs[now]],lazy[now]); val[ls[now]]=mul(val[ls[now]],lazy[now]); val[rs[now]]=mul(val[rs[now]],lazy[now]); lazy[now]=F; } void build(int &now,int left,int right) { now=++tot;lazy[now]=F; if (left==right) { val[now].a[1][1]=0;val[now].a[1][2]=1; return; } int mid=left+right>>1; build(ls[now],left,mid); build(rs[now],mid+1,right); val[now]=add(val[ls[now]],val[rs[now]]); } void modify(int now,int left,int right,int l,int r,int x) { pushdown(now,left,right); if ((left==l) && (right==r)) { matrix ret=f_pow(x); lazy[now]=mul(lazy[now],ret); val[now]=mul(val[now],ret); return; } int mid=left+right>>1; if (r<=mid) modify(ls[now],left,mid,l,r,x); else if (l>=mid+1) modify(rs[now],mid+1,right,l,r,x); else { modify(ls[now],left,mid,l,mid,x); modify(rs[now],mid+1,right,mid+1,r,x); } val[now]=add(val[ls[now]],val[rs[now]]); } matrix ask(int now,int left,int right,int l,int r) { pushdown(now,left,right); if ((left==l) && (right==r)) return val[now]; int mid=left+right>>1; if (r<=mid) return ask(ls[now],left,mid,l,r); else if (l>=mid+1) return ask(rs[now],mid+1,right,l,r); else return add(ask(ls[now],left,mid,l,mid),ask(rs[now],mid+1,right,mid+1,r)); } int main() { base[0].a[1][1]=0;base[0].a[1][2]=base[0].a[2][1]=base[0].a[2][2]=1; F.a[1][1]=F.a[2][2]=1;F.a[1][2]=F.a[2][1]=0; for (int i=1;i<=30;i++) base[i]=mul(base[i-1],base[i-1]); n=read();m=read(); build(root,1,n); for (int i=1;i<=n;i++) { x=read(); modify(root,1,n,i,i,x-1); } for (int i=1;i<=m;i++) { type=read(); if (type==1) { x=read();y=read();z=read(); modify(root,1,n,x,y,z); } else { x=read();y=read(); matrix ret=ask(root,1,n,x,y); printf("%d\n",ret.a[1][2]%mod); } } return 0; }