E. Sasha and Array 矩阵快速幂 + 线段树
Posted echozqn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了E. Sasha and Array 矩阵快速幂 + 线段树相关的知识,希望对你有一定的参考价值。
这个题目没有特别难,需要自己仔细想想,一开始我想了一个方法,不对,而且还很复杂,然后lj提示了我一下说矩阵乘,然后再仔细想想就知道怎么写了。
这个就是直接把矩阵放到线段树里面去了。
注意优化,降低复杂度。
#include <cstring> #include <iostream> #include <algorithm> #include <cstdio> #include <cstdlib> #include <queue> #define inf 0x3f3f3f3f using namespace std; typedef long long ll; const int mod=1e9+7; struct mat ll m[3][3]; unite,zero; mat operator*(mat a,mat b) mat ans; for(int i=1;i<=2;i++) for(int j=1;j<=2;j++) ll x = 0; for(int k=1;k<=2;k++) x+=(a.m[i][k]*b.m[k][j])%mod; ans.m[i][j]=x%mod; return ans; mat operator+(mat a,mat b) mat ans; for(int i=1;i<=2;i++) for(int j=1;j<=2;j++) ans.m[i][j]=(a.m[i][j]+b.m[i][j])%mod; return ans; mat mod_pow(mat a,ll n) mat ans=unite; while(n) if(n&1) ans=ans*a; a=a*a; n>>=1; return ans; const int maxn=1e5+10; mat sum[maxn*4],a,lazy[maxn*4]; ll v[maxn]; void init() a.m[1][1]=a.m[1][2]=a.m[2][1]=1,a.m[2][2]=0; for(int i=0;i<3;i++) unite.m[i][i]=1; for(int i=0;i<3;i++) for(int j=0;j<3;j++) zero.m[i][j]=0; void push_up(int id) sum[id]=sum[id<<1]+sum[id<<1|1]; void build(int id,int l,int r) lazy[id]=unite; if(l==r) sum[id]=mod_pow(a,v[l]); return ; int mid=(l+r)>>1; build(id<<1,l,mid); build(id<<1|1,mid+1,r); push_up(id); bool same(mat a,mat b) for(int i=1;i<=2;i++) for(int j=1;j<=2;j++) if(a.m[i][j]!=b.m[i][j]) return false; return true; void push_down(int id) if(same(lazy[id],unite)) return ; sum[id<<1]=sum[id<<1]*lazy[id]; sum[id<<1|1]=sum[id<<1|1]*lazy[id]; lazy[id<<1]=lazy[id<<1]*lazy[id]; lazy[id<<1|1]=lazy[id<<1|1]*lazy[id]; lazy[id]=unite; void update(int id,int l,int r,int x,int y,mat val) if(x<=l&&y>=r) lazy[id]=lazy[id]*val; sum[id]=sum[id]*val; return ; push_down(id); int mid=(l+r)>>1; if(x<=mid) update(id<<1,l,mid,x,y,val); if(y>mid) update(id<<1|1,mid+1,r,x,y,val); push_up(id); mat query(int id,int l,int r,int x,int y) if(x<=l&&y>=r) return sum[id]; mat ans=zero; int mid=(l+r)>>1; push_down(id); if(x<=mid) ans=ans+query(id<<1,l,mid,x,y); if(y>mid) ans=ans+query(id<<1|1,mid+1,r,x,y); return ans; int main() init(); int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%lld",&v[i]); build(1,1,n); while(m--) int opt; ll l,r,x; scanf("%d",&opt); if(opt==1) scanf("%lld%lld%lld",&l,&r,&x); mat val=mod_pow(a,x); update(1,1,n,l,r,val); else scanf("%lld%lld",&l,&r); mat ans=query(1,1,n,l,r); printf("%lld\n",ans.m[1][2]); return 0;
以上是关于E. Sasha and Array 矩阵快速幂 + 线段树的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces718 C. Sasha and Array(线段树维护矩阵,矩阵快速幂求斐波那契数列,矩阵乘法结合律)