\(\text{Problem}\)

\(\text{Solution}\)

\(\text{Fibonacci}\) 数列有一个性质:若 \(H_1=a,H_2=b,H_n=H_{n-2}+H_{n-1}\)

则有 \(H_n=a\cdot F_{n-2}+b\cdot F_{n-1}\)

有了这个性质后,对一段区间加斐波那契数列后,我们可以 \(O(1)\) 知道任意一位加的数是多少(当然是预处理出斐波那契数列后)

也就是说维护这段区间前两位加的数 \({a,b}\) 即可

对于一段区间求区间和即 \(ans=a\cdot[(\sum_{i=1}^{r-l-1}F_i)+1]+b\cdot\sum_{i=1}^{r-l}F_i\)

线段树维护每段区间加的 \(a,b\) 即可

\(\text{Code}\)

#include<cstdio>
#define ls (p << 1)
#define rs (ls | 1)
typedef long long LL;
using namespace std; const int N = 1e5 + 5;
const LL P = 1e9 + 9;
int n, m;
LL a[N], F[N], sF[N];
LL sum[N * 4], tg1[N * 4], tg2[N * 4]; void pushup(int p) {sum[p] = (sum[ls] + sum[rs]) % P;}
void update1(int l, int r, int p, int x, int v)
{
if (l == r) return void(tg1[p] = sum[p] = v);
int mid = (l + r) >> 1;
if (x <= mid) update1(l, mid, ls, x, v);
else update1(mid + 1, r, rs, x, v);
pushup(p);
}
void change(int l, int r, int p, LL v1, LL v2)
{
sum[p] = (sum[p] + v1 * (sF[(r - l - 1)<0?0:(r - l - 1)] + 1) % P + v2 * sF[r - l] % P) % P;
tg1[p] = (tg1[p] + v1) % P, tg2[p] = (tg2[p] + v2) % P;
}
void pushdown(int l, int r, int p)
{
if (!tg1[p] && !tg2[p]) return;
int mid = (l + r) >> 1;
change(l, mid, ls, tg1[p], tg2[p]);
LL v1 = (tg1[p] * F[mid - l] % P + tg2[p] * F[mid - l + 1] % P) % P;
LL v2 = (tg1[p] * F[mid - l + 1] % P + tg2[p] * F[mid - l + 2] % P) % P;
change(mid + 1, r, rs, v1, v2);
tg1[p] = 0, tg2[p] = 0;
}
void update2(int l, int r, int p, int x, int y, LL v1, LL v2)
{
if (x <= l && r <= y) return void(change(l, r, p, v1, v2));
int mid = (l + r) >> 1;
pushdown(l, r, p);
if (x <= mid) update2(l, mid, ls, x, y, v1, v2);
LL a = v1, b = v2;
if (l <= x && x <= mid) a = (v1 * F[mid - x] % P + v2 * F[mid - x + 1] % P) % P,
b = (v1 * F[mid - x + 1] % P + v2 * F[mid - x + 2] % P) % P;
else if (l > x && x <= mid) a = (v1 * F[mid - l] % P + v2 * F[mid - l + 1] % P) % P,
b = (v1 * F[mid - l + 1] % P + v2 * F[mid - l + 2] % P) % P;
if (y > mid) update2(mid + 1, r, rs, x, y, a, b);
pushup(p);
}
LL query(int l, int r, int p, int x, int y)
{
if (x <= l && r <= y) return sum[p];
int mid = (l + r) >> 1; LL ret = 0;
pushdown(l, r, p);
if (x <= mid) ret = query(l, mid, ls, x, y);
if (y > mid) ret = (ret + query(mid + 1, r, rs, x, y)) % P;
return ret;
} int main()
{
scanf("%d%d", &n, &m);
for(int i = 1, x; i <= n; i++) scanf("%d", &x), update1(1, n, 1, i, x);
F[1] = 1, F[2] = 1, sF[1] = 1, sF[2] = 2;
for(int i = 3; i <= n; i++) F[i] = (F[i - 1] + F[i - 2]) % P;
for(int i = 3; i <= n; i++) sF[i] = (sF[i - 1] + F[i]) % P;
for(int op, l, r; m; --m)
{
scanf("%d%d%d", &op, &l, &r);
if (op == 1) update2(1, n, 1, l, r, F[1], F[2]);
else printf("%lld\n", query(1, n, 1, l, r));
}
}

JZOJ.4724 斐波那契的更多相关文章

  1. C#求斐波那契数列第30项的值(递归和非递归)

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  2. python迭代器实现斐波拉契求值

    斐波那契数列(Fibonacci sequence),又称黄金分割数列,也称为"兔子数列":F(0)=0,F(1)=1,F(n)=F(n-1)+F(n-2)(n≥2,n∈N*).例 ...

  3. Ural 1225. Flags 斐波那契DP

    1225. Flags Time limit: 1.0 secondMemory limit: 64 MB On the Day of the Flag of Russia a shop-owner ...

  4. 斐波拉契数列加强版——时间复杂度O(1),空间复杂度O(1)

    对于斐波拉契经典问题,我们都非常熟悉,通过递推公式F(n) = F(n - ) + F(n - ),我们可以在线性时间内求出第n项F(n),现在考虑斐波拉契的加强版,我们要求的项数n的范围为int范围 ...

  5. js中的斐波那契数列法

    //斐波那契数列:1,2,3,5,8,13…… //从第3个起的第n个等于前两个之和 //解法1: var n1 = 1,n2 = 2; for(var i=3;i<101;i++){ var ...

  6. 剑指Offer面试题:8.斐波那契数列

    一.题目:斐波那契数列 题目:写一个函数,输入n,求斐波那契(Fibonacci)数列的第n项.斐波那契数列的定义如下: 二.效率很低的解法 很多C/C++/C#/Java语言教科书在讲述递归函数的时 ...

  7. 算法: 斐波那契数列C/C++实现

    斐波那契数列: 1,1,2,3,5,8,13,21,34,....     //求斐波那契数列第n项的值 //1,1,2,3,5,8,13,21,34... //1.递归: //缺点:当n过大时,递归 ...

  8. 洛谷P1962 斐波那契数列 || P1349 广义斐波那契数列[矩阵乘法]

    P1962 斐波那契数列 大家都知道,斐波那契数列是满足如下性质的一个数列: • f(1) = 1 • f(2) = 1 • f(n) = f(n-1) + f(n-2) (n ≥ 2 且 n 为整数 ...

  9. Python递归及斐波那契数列

    递归函数 在函数内部,可以调用其他函数.如果一个函数在内部调用自身本身,这个函数就是递归函数.举个例子,我们来计算阶乘 n! = 1 * 2 * 3 * ... * n,用函数 fact(n)表示,可 ...

  10. 简单Java算法程序实现!斐波那契数列函数~

    java编程基础--斐波那契数列 问题描述:一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法. 思路:可能出现的情况:(1) n=1 ,一种方法 ;(2)n=2 ...

随机推荐

  1. ArcGIS 通过字段计算 设置顺序编码

    地块编号="前缀" & left("0000",4-len( [FID]+1)) & ([FID] +1)

  2. js-day05-对象

    为什么要学习对象 没有对象时,保存网站用户信息时不方便,很难区别 对象是什么 1.对象是一种数据类型 2.无序的数据集合 对象有什么特点 1.无序的数据的集合 2.可以详细的描述某个事物' 对象使用 ...

  3. 【Hadoop面试】基础概念、HDFS、MapReduce、Yarn、实战

    一.Hadoop概念及架构 1.是否看过Hadoop源码 2.正常工作的hadoop集群中hadoop都分别需要启动哪些进程,他们的作用分别是什么 3.hadoop和spark中的文件缓存方式 4.h ...

  4. instanceof和Class.isAssignableFrom的区别

    1. Class.isAssignableFrom 偶然看见同事写的一段代码是这样的 if( AfterRender.class.isAssignableFrom( assembly.getClass ...

  5. 区块链,中心去,何曾着眼看君王?用Go语言实现区块链技术,通过Golang秒懂区块链

    区块链技术并不是什么高级概念,它并不比量子力学.泡利不相容原则.哥德巴赫猜想更难以理解,但却也不是什么类似"时间就是金钱"这种妇孺皆知的浅显道理.区块链其实是一套统筹组织记录的方法 ...

  6. 【进阶篇】Redis实战之Jedis使用技巧详解

    一.摘要 在上一篇文章中,我们详细的介绍了 redis 的安装和常见的操作命令,以及可视化工具的介绍. 刚知道服务端的操作知识,还是远远不够的,如果想要真正在项目中得到应用,我们还需要一个 redis ...

  7. Linux基础:ssh与scp

    登陆 登陆服务器 ssh user@hostname user: 用户名 hostname :IP地址或域名 第一次登陆会提示 The authenticity of host '123.57.47. ...

  8. Linux安装&卸载mysql5.7

    Linux系统下卸载mysql 停止mysql服务 systemctl stop mysqld.service 查看安装的mysql服务 rpm -qa|grep -i mysql 删除安装的mysq ...

  9. yolov5数据集制作 数据集分割+voc格式转txt格式代码

    先上数据集分割代码 网上没找到合适的 自己写了一个 分割比例为0.6 :0.2 :0.2 import os import random oriImgDir = "./change14img ...

  10. Java的深拷贝和浅拷贝的区别

    一.拷贝的引入 (1).引用拷贝 创建一个指向对象的引用变量的拷贝. Teacher teacher = new Teacher("Taylor",26); Teacher oth ...