题解 斐波那契

传送门

发现矩阵乘法对于加法有结合律,所以按题意线段树维护即可

点击查看代码
#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;
}
posted @ 2022-03-04 14:18  Administrator-09  阅读(2)  评论(0编辑  收藏  举报