题解 斐波那契
发现矩阵乘法对于加法有结合律,所以按题意线段树维护即可
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n, m;
int a[N];
const ll mod=1004535809;
inline ll md(ll a) {return a>=mod?a-mod:a;}
struct matrix{
int n, m;
ll a[3][3];
matrix(){n=0; m=0; memset(a, 0, sizeof(a));}
matrix(int x, int y){n=x; m=y; memset(a, 0, sizeof(a));}
void resize(int x, int y) {n=x; m=y; memset(a, 0, sizeof(a));}
void put() {for (int i=1; i<=n; ++i) {for (int j=1; j<=m; ++j) cout<<a[i][j]<<' '; cout<<endl;}cout<<endl;}
inline ll* operator [] (int t) {return a[t];}
inline matrix operator + (matrix b) {
matrix ans(n, m);
for (int i=1; i<=n; ++i)
for (int j=1; j<=m; ++j)
ans[i][j]=md(a[i][j]+b[i][j]);
return ans;
}
inline matrix operator * (matrix b) {
matrix ans(n, b.m);
for (int i=1; i<=n; ++i)
for (int k=1; k<=m; ++k)
for (int j=1; j<=b.m; ++j)
ans[i][j]=(ans[i][j]+a[i][k]*b[k][j])%mod;
return ans;
}
}I, base, tran;
inline matrix qpow(matrix a, ll b) {matrix ans=I; for (; b; a=a*a,b>>=1) if (b&1) ans=ans*a; return ans;}
namespace task1{
int tl[N<<2], tr[N<<2];
matrix val[N<<2], tag[N<<2];
#define tl(p) tl[p]
#define tr(p) tr[p]
#define val(p) val[p]
#define tag(p) tag[p]
#define pushup(p) val(p)=val(p<<1)+val(p<<1|1)
void spread(int p) {
val(p<<1)=val(p<<1)*tag(p); tag(p<<1)=tag(p<<1)*tag(p);
val(p<<1|1)=val(p<<1|1)*tag(p); tag(p<<1|1)=tag(p<<1|1)*tag(p);
tag(p)=I;
}
void build(int p, int l, int r) {
tl(p)=l; tr(p)=r; tag(p)=I;
if (l==r) {val(p)=base*qpow(tran, a[l]-1); return ;}
int mid=(l+r)>>1;
build(p<<1, l, mid);
build(p<<1|1, mid+1, r);
pushup(p);
}
void upd(int p, int l, int r, matrix dat) {
if (l<=tl(p)&&r>=tr(p)) {val(p)=val(p)*dat; tag(p)=tag(p)*dat; return ;}
spread(p);
int mid=(tl(p)+tr(p))>>1;
if (l<=mid) upd(p<<1, l, r, dat);
if (r>mid) upd(p<<1|1, l, r, dat);
pushup(p);
}
matrix query(int p, int l, int r) {
if (l<=tl(p)&&r>=tr(p)) return val(p);
spread(p);
int mid=(tl(p)+tr(p))>>1;
if (l<=mid&&r>mid) return query(p<<1, l, r)+query(p<<1|1, l, r);
else if (l<=mid) return query(p<<1, l, r);
else return query(p<<1|1, l, r);
}
void solve() {
build(1, 1, n);
matrix tem;
for (int i=1,l,r,x; i<=m; ++i) {
if (read()&1) {
l=read(); r=read(); x=read();
tem=qpow(tran, x);
upd(1, l, r, tem);
}
else {
l=read(); r=read();
tem=query(1, l, r);
printf("%lld\n", tem[1][1]);
}
}
}
}
signed main()
{
freopen("fib.in", "r", stdin);
freopen("fib.out", "w", stdout);
n=read(); m=read();
for (int i=1; i<=n; ++i) a[i]=read();
I.resize(2, 2); I[1][1]=I[2][2]=1;
base.resize(1, 2); base[1][1]=base[1][2]=1;
tran.resize(2, 2); tran[1][2]=tran[2][1]=tran[2][2]=1;
task1::solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】