CF718C Sasha and Array
题意
给定长度为 $ n $ 的序列 $ a$ 要求支持 $ m $ 次操作:
$ opt_1 $ :给定 $ fr_i , to_i , val_i,\forall i \in [fr_i , to_i] , a_i = a_i + val_i $;
$ opt_2 $ :给定 $ fr_i , to_i $ 求 $ \sum\limits_{i=fr_i}^{to_i} f(a_i) $ 对 $10^9+7$ 取模后的结果。
其中 $ f(i) $ 表示斐波那契数列第 $ i$ 项,$ f(i) = \left\{\begin{aligned} 1 \space (n \le 2) \\ f(n-1)+f(n-2) \space (n\ge 3) \end{aligned}\right. $
数据范围
$ n,m \leq 100000 $。
Solution
发现题目要求区间操作,考虑线段树维护。
对于斐波那契数列,显然地可以构造矩阵转移:
$ \begin{bmatrix} f(i) & f(i-1) \end{bmatrix} \times \begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix} = \begin{bmatrix} f(i+1) & f(i) \end{bmatrix} $
且矩阵满足结合律,用线段树+矩阵快速幂维护即可。
一些细节
初始化线段树时,对值为 $ 1 $ 的结点都置为 $ \begin{bmatrix}1&0\end{bmatrix} $ ,其他节点赋值为 $ \begin{bmatrix} 1 & 1 \end{bmatrix} \times \begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix} ^{n-2}$。
code
#include<bits/stdc++.h>
using namespace std;
#define mod(a) a>1000000007?a-1000000007:a
static inline char Get_Char()
{
static char buffer[100000],*S=buffer,*T=buffer;
return (S==T&&(T=(S=buffer)+fread(buffer,1,100000,stdin),S==T)?EOF:*S++);
}
inline int read()
{
int res=0,flag=1;
char ch=Get_Char();
while(!isalnum(ch)) (ch=='-')?flag=-1:1,ch=Get_Char();
while(isalnum(ch)) res=res*10+ch-'0',ch=Get_Char();
return res*flag;
}
inline void write(int x)
{
char buf[20]; int len=0;
if(x<=0) putchar((x==0)?'0':'-'); x=abs(x);
while(x!=0) buf[++len]=x%10+'0',x/=10;
while(len!=0) putchar(buf[len--]);
putchar('\n');
}
const int mod=1e9+7;
struct matrix
{
int val[2][2];
void Set()
{
val[0][0]=val[1][1]=1;
val[0][1]=val[1][0]=0;
return ;
}
struct matrix operator *(const struct matrix &other)const
{
struct matrix res;
res.val[0][0]=mod((long long)this->val[0][0]*other.val[0][0]%mod+(long long)this->val[0][1]*other.val[1][0]%mod);
res.val[1][0]=mod((long long)this->val[1][0]*other.val[0][0]%mod+(long long)this->val[1][1]*other.val[1][0]%mod);
res.val[0][1]=mod((long long)this->val[0][0]*other.val[0][1]%mod+(long long)this->val[0][1]*other.val[1][1]%mod);
res.val[1][1]=mod((long long)this->val[1][0]*other.val[0][1]%mod+(long long)this->val[1][1]*other.val[1][1]%mod);
return res;
}
struct matrix operator +(const struct matrix &other)const
{
struct matrix res;
res.val[0][0]=mod(this->val[0][0]+other.val[0][0]);
res.val[0][1]=mod(this->val[0][1]+other.val[0][1]);
res.val[1][0]=mod(this->val[1][0]+other.val[1][0]);
res.val[1][1]=mod(this->val[1][1]+other.val[1][1]);
return res;
}
/*
void print()
{
for(int i=0;i<=1;i++)
{
for(int j=0;j<=1;j++)
cout<<val[i][j]<<" ";
cout<<endl;
}
return ;
}*/
};
struct node
{
struct matrix data,tag;
};
struct matrix base[50];
struct node nd[400010];
int val[100010];
struct matrix quick(int p)//a=f(now+p)
{
struct matrix res;
res.Set();
for(int i=1;i<=46&&p!=0;i++)
{
if(p&1)
res=res*base[i];
p>>=1;
}
return res;
}
void pushdown(int id)
{
nd[id<<1].tag=nd[id<<1].tag*nd[id].tag;
nd[id<<1|1].tag=nd[id<<1|1].tag*nd[id].tag;
nd[id<<1].data=nd[id<<1].data*nd[id].tag;
nd[id<<1|1].data=nd[id<<1|1].data*nd[id].tag;
nd[id].tag.Set();
return ;
}
void pushup(int id)
{
// nd[id].sum=(nd[id<<1].sum+nd[id<<1|1].sum)%mod;
nd[id].data=nd[id<<1].data+nd[id<<1|1].data;
return ;
}
void build(int left,int right,int id)
{
nd[id].tag.Set();
if(left==right)
{
if(val[left]==1)
nd[id].data.val[0][0]=1;
else
nd[id].data.val[0][0]=nd[id].data.val[0][1]=1;
if(val[left]>2)
nd[id].data=nd[id].data*quick(val[left]-2);
return ;
}
int mid=(left+right)>>1;
build(left,mid,id<<1);
build(mid+1,right,id<<1|1);
pushup(id);
return ;
}
void modify(int left,int right,int id,int start,int end,int value)
{
if(right<start||end<left)
return ;
if(start<=left&&right<=end)
{
struct matrix tmp=quick(value);
nd[id].data=nd[id].data*tmp;
nd[id].tag=nd[id].tag*tmp;
return ;
}
int mid=(left+right)>>1;
pushdown(id);
modify(left,mid,id<<1,start,end,value);
modify(mid+1,right,id<<1|1,start,end,value);
pushup(id);
return ;
}
int query(int left,int right,int id,int start,int end)
{
if(right<start||end<left)
return 0;
if(start<=left&&right<=end)
return mod(nd[id].data.val[0][0]);
int mid=(left+right)>>1;
pushdown(id);
int ansl=query(left,mid,id<<1,start,end);
int ansr=query(mid+1,right,id<<1|1,start,end);
return mod(ansl+ansr);
}
int main(int argc,const char *argv[])
{
base[1].val[0][0]=base[1].val[0][1]=base[1].val[1][0]=1;
int n=read(),q=read();
for(int i=2;i<=46;i++)
base[i]=base[i-1]*base[i-1];
for(int i=1;i<=n;i++)
val[i]=read();
build(1,n,1);
for(int i=1;i<=q;i++)
{
int opt=read(),l=read(),r=read();
if(opt==1)
{
int value=read();
modify(1,n,1,l,r,value);
}
if(opt==2)
write(query(1,n,1,l,r));
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】