CF718C Sasha and Array
题目大意
在本题中,我们用 来表示第 个斐波那契数 。
给定一个 个数的序列 。
有 次操作,操作有两种:
-
将 加上 。
-
求 。
,。
解题思路
两个操作,区间加,区间求和。
显然线段树。
斐波那契数怎么搞?
预处理显然爆。
显然用 的矩阵快速幂来求。
设 ,则有 。
由于矩阵具有分配律,即 ,所以对于一段区间的矩阵可以相加维护,所以 。
线段树满足所有条件!!!
线段树上每个点都搞成一个矩阵即可。
具体请看代码。
CODE
#include <bits/stdc++.h>
#define int long long
inline int read()
{
int s = 0, f = 0;
char ch = getchar();
while (!isdigit(ch))
f |= (ch == '-'), ch = getchar();
while (isdigit(ch))
s = (s << 1) + (s << 3) + ch - '0', ch = getchar();
return f ? -s : s;
}
using namespace std;
const int _ = 1e5 + 5;
const int INF = 1e9 + 7;
const int mod = 1e9 + 7;
struct Matrix
{
int a[3][3];
Matrix() { memset(a, false, sizeof a); }
void Init() { a[1][1] = a[2][2] = 1, a[1][2] = a[2][1] = 0; }
bool pd() { return a[1][1] == 1 && a[2][2] == 1 && a[1][2] == 0 && a[2][1] == 0; }
Matrix operator+(const Matrix b)
{
Matrix res;
for (int i = 1; i <= 2; ++i)
for (int j = 1; j <= 2; ++j)
res.a[i][j] = (a[i][j] + b.a[i][j]) % mod;
return res;
}
Matrix operator*(const Matrix b)
{
Matrix res;
for (int k = 1; k <= 2; ++k)
for (int i = 1; i <= 2; ++i)
for (int j = 1; j <= 2; ++j)
res.a[i][j] = (res.a[i][j] + a[i][k] * b.a[k][j]) % mod;
return res;
}
Matrix operator^(int b)
{
Matrix res, Base;
for (int i = 1; i <= 2; ++i)
res.a[i][i] = 1;
for (int i = 1; i <= 2; ++i)
for (int j = 1; j <= 2; ++j)
Base.a[i][j] = a[i][j];
while (b)
{
if (b & 1)
res = res * Base;
Base = Base * Base;
b >>= 1;
}
return res;
}
} base, ans;
int n, m, a[_];
namespace Seg_tree
{
#define lson i << 1
#define rson i << 1 | 1
struct Tree
{
Matrix sum, lazy;
} tree[_ << 2];
void Push_up(int i) { tree[i].sum = tree[lson].sum + tree[rson].sum; }
void Build(int i, int l, int r)
{
tree[i].lazy.Init();
if (l == r)
{
if (a[l] == 1)
tree[i].sum.a[1][1] = 1;
else if (a[l] == 2)
tree[i].sum.a[1][1] = tree[i].sum.a[1][2] = 1;
else
tree[i].sum = ans * (base ^ (a[l] - 2));
return;
}
int mid = (l + r) >> 1;
Build(lson, l, mid), Build(rson, mid + 1, r);
Push_up(i);
}
void Push_down(int i)
{
if (tree[i].lazy.pd())
return;
tree[lson].lazy = tree[lson].lazy * tree[i].lazy;
tree[rson].lazy = tree[rson].lazy * tree[i].lazy;
tree[lson].sum = tree[lson].sum * tree[i].lazy;
tree[rson].sum = tree[rson].sum * tree[i].lazy;
tree[i].lazy.Init();
}
void Modify(int i, int l, int r, int L, int R, Matrix k)
{
if (L <= l && r <= R)
{
tree[i].lazy = tree[i].lazy * k, tree[i].sum = tree[i].sum * k;
return;
}
Push_down(i);
int mid = (l + r) >> 1;
if (mid >= L)
Modify(lson, l, mid, L, R, k);
if (mid < R)
Modify(rson, mid + 1, r, L, R, k);
Push_up(i);
}
int Query(int i, int l, int r, int L, int R)
{
if (L <= l && r <= R)
return tree[i].sum.a[1][1];
Push_down(i);
int mid = (l + r) >> 1, ans = 0;
if (mid >= L)
ans = (ans + Query(lson, l, mid, L, R)) % mod;
if (mid < R)
ans = (ans + Query(rson, mid + 1, r, L, R)) % mod;
return ans;
}
}
signed main()
{
base.a[1][1] = base.a[1][2] = base.a[2][1] = 1;
ans.a[1][1] = ans.a[1][2] = 1;
n = read(), m = read();
for (int i = 1; i <= n; ++i)
a[i] = read();
Seg_tree::Build(1, 1, n);
for (int i = 1, opt, l, r, k; i <= m; ++i)
{
opt = read(), l = read(), r = read();
if (opt == 1)
{
k = read();
Seg_tree::Modify(1, 1, n, l, r, base ^ k);
}
else
{
printf("%lld\n", Seg_tree::Query(1, 1, n, l, r));
}
}
return 0;
}
本文来自博客园,作者:蒟蒻orz,转载请注明原文链接:https://www.cnblogs.com/orzz/p/18122100
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】