CF718C Sasha and Array
题面
定义 为 斐波那契数列的第 项的数。你需要实现一个数据结构 ,支持:
1 l r x
:将 的数加上 。
2 l r
:求 。
思路
不难看出是线段树,但是怎么计算 呢?
如果暴力去计算 ,显然是不靠谱的(时间复杂度是 )。
如果使用斐波那契末项计算公式(参见 P1720 月落乌啼算钱(斐波那契数列))也不靠谱,不容易维护。
如果做过 P1962 斐波那契数列 的同学可能知道,可以用矩阵快速幂计算。
大致公式如下:
OI-Wiki 上有证明。
然后就是维护一个区间修改区间查询线段树。时间复杂度是 。
代码
代码里面有封装好了的矩阵模板,供大家随意使用。
#include <bits/stdc++.h>
#define ls (i<<1)
#define rs (i<<1|1)
#define mid ((l+r)>>1)
#define int long long
using namespace std;
const int MOD = 1e9+7;
struct Matrix{
int a[3][3];
const int size = 2;
Matrix(){
memset(a,0,sizeof(a));
}
Matrix(int aba){
a[aba][aba]=1;
a[aba][aba+1]=0;
a[aba+1][aba]=0;
a[aba+1][aba+1]=1;
}
Matrix(int A,int b,int c,int d){
a[1][1]=A;
a[1][2]=b;
a[2][1]=c;
a[2][2]=d;
}
Matrix operator*(const Matrix &ano) const {
Matrix ans;
for(int i=1;i<=size;i++){
for(int k=1;k<=size;k++){
for(int j=1;j<=size;j++){
ans.a[i][k]=(ans.a[i][k]+a[i][j]*ano.a[j][k])%MOD;
}
}
}
return ans;
}
Matrix operator+(const Matrix aa){
Matrix res;
for(int i=1;i<=size;i++){
for(int j=1;j<=size;j++){
res.a[i][j]=a[i][j]+aa.a[i][j];
res.a[i][j]%=MOD;
}
}
return res;
}
void operator=(const Matrix A){
for(int i=1;i<=size;i++){
for(int j=1;j<=size;j++){
a[i][j]=A.a[i][j];
}
}
}
bool empty(){
return (a[1][1]==0)&&(a[1][2]==0)&&(a[2][1]==0)&&(a[2][2]==0);
}
Matrix operator^(int power){
Matrix res(1);
Matrix base = (*this);
while(power){
if(power&1){
res=res*base;
}
base=base*base;
power>>=1;
}
return res;
}
};
const int SIZE = 1e5+5;
Matrix t[SIZE<<2],tag[SIZE<<2];
int v[SIZE];
const Matrix unit(1);
int n,m;
inline void pushup(int i){
t[i]=t[ls]+t[rs];
}
void build(int i,int l,int r){
tag[i]=unit;
if(l==r){
t[i]=Matrix(1,1,0,0)*(Matrix(1,1,1,0)^(v[l]-1));
return;
}
build(ls,l,mid);
build(rs,mid+1,r);
pushup(i);
}
void pushdown(int i){
if(tag[i].empty()){
return;
}
t[ls]=t[ls]*tag[i];
tag[ls]=tag[ls]*tag[i];
t[rs]=t[rs]*tag[i];
tag[rs]=tag[rs]*tag[i];
tag[i]=unit;
}
void update(int i,int ql,int qr,int l,int r,Matrix x){
if(ql<=l && qr>=r){
t[i]=t[i]*x;
tag[i]=tag[i]*x;
return;
}
pushdown(i);
if(ql<=mid){
update(ls,ql,qr,l,mid,x);
}
if(qr>mid){
update(rs,ql,qr,mid+1,r,x);
}
pushup(i);
}
Matrix query(int i,int ql,int qr,int l,int r){
if(ql<=l && qr>=r){
return t[i];
}
pushdown(i);
Matrix res;
if(ql<=mid){
res = res + query(ls,ql,qr,l,mid);
}
if(qr > mid){
res = res+query(rs,ql,qr,mid+1,r);
}
return res;
}
signed main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>v[i];
}
build(1,1,n);
while(m--){
int op,l,r,x;
cin>>op;
if(op==1){
cin>>l>>r>>x;
update(1,l,r,1,n,Matrix(1,1,1,0)^x);
}
else{
cin>>l>>r;
cout<<(query(1,l,r,1,n).a[1][2]%MOD)<<'\n';
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!