假如F[1] = a, F[2] = B, F[n] = F[n - 1] + F[n - 2]。

写成矩阵表示形式可以很快发现F[n] = f[n - 1] * b + f[n - 2] * a。 f[n] 是斐波那契数列

也就是我们如果知道一段区间的前两个数增加了多少,可以很快计算出这段区间的第k个数增加了多少

通过简单的公式叠加也能求和

F[n]  = f[n - 1] * b + f[n - 2] * a

F[n - 1] = f[n - 2] * b + f[n - 3] * a

.....

F[3] = f[2] * b + f[1] * a

F[2] = 1 * b    +        0

F[1] =    0       +        a

令G[n] = 0 + 1 + f[2] + f[3] + .... + f[n - 1]

K[n]  = 1 + 0 + f[1] + f[2] + .... f[n - 2] ,那么F[n] = G[n] * b + K[n] * a

线段树结点维护a,b两个延迟标记,分别表示第一个数和第二个数增加了多少

注意在PushDown和update的时候还要通过F[n]  = f[n - 1] * b + f[n - 2] * a计算出右子节点的前两个数应该增加的值

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream> using namespace std;
typedef long long LL; const int maxn = 3e5 + 10;
const int mod = 1e9 + 9;
#define lson idx << 1, l, mid
#define rson idx << 1 | 1, mid + 1, r LL f[maxn], F[maxn], G[maxn];
void init() {
f[1] = G[1] = 1;
F[0] = 1;
F[1] = 1;
for(int i = 2; i < maxn; i++) {
f[i] = (f[i - 1] + f[i - 2]) % mod;
G[i] = (G[i - 1] + f[i]) % mod;
F[i] = (F[i - 1] + f[i - 1]) % mod;
}
// F[i] = 1 + 0 + f[1] + f[2] + f[3] + ....f[i - 1]
// G[i] = 0 + f[1] + f[2] + f[3] + ....f[i]
}
LL sum[maxn << 2];
LL a[maxn << 2], b[maxn << 2];
void PushUp(int idx) {
sum[idx] = (sum[idx << 1] + sum[idx << 1 | 1]) % mod;
}
void build(int idx, int l, int r) {
a[idx] = b[idx] = 0;
if(l == r) {
scanf("%I64d", &sum[idx]);
} else {
int mid = (r + l) >> 1;
build(lson);
build(rson);
PushUp(idx);
}
} void maintain(int idx, int l,int r, int v1, int v2) {
int len = r - l + 1;
a[idx] = (a[idx] + v1) % mod;
b[idx] = (b[idx] + v2) % mod;
sum[idx] = (sum[idx] + G[len - 1] * v2 % mod + F[len - 1] * v1 % mod) % mod;
}
void PushDown(int idx, int l, int r) {
if(a[idx] != 0 || b[idx] != 0) {
int mid = (r + l) >> 1;
maintain(lson, a[idx], b[idx]);
int len = mid - l + 1;
int v1 = (f[len] * b[idx] + f[len - 1] * a[idx]) % mod;
int v2 = (f[len + 1] * b[idx] + f[len] * a[idx]) % mod;
maintain(rson, v1, v2);
a[idx] = b[idx] = 0;
}
}
void update(int idx, int l, int r, int tl, int tr, int v1, int v2) {
if(tl <= l && tr >= r) {
maintain(idx, l, r, v1, v2);
} else {
PushDown(idx, l, r);
int mid = (r + l) >> 1;
if(tl <= mid) update(lson, tl, tr, v1, v2);
if(tr > mid) {
LL h1 = v1, h2 = v2;
if(tl <= mid) {
int len = mid - max(tl,l) + 1;
h1 = (f[len] * v2 + f[len - 1] * v1) % mod;
h2 = (f[len + 1] * v2 + f[len] * v1) % mod;
}
update(rson, tl, tr, h1, h2);
}
PushUp(idx);
}
}
LL query(int idx, int l, int r, int tl, int tr) {
if(tl <= l && tr >= r) return sum[idx];
else {
PushDown(idx, l, r);
int mid = (r + l) >> 1;
LL ans = 0;
if(tl <= mid) ans = (ans + query(lson, tl, tr)) % mod;
if(tr > mid) ans = (ans + query(rson, tl, tr)) % mod;
return ans;
}
}
int main() {
init();
int n, m;
scanf("%d%d", &n, &m);
build(1, 1, n);
for(int i = 1; i <= m; i++) {
int op, l, r;
scanf("%d%d%d", &op, &l, &r);
if(op == 1) update(1, 1, n, l, r, 1, 1);
else {
LL ans = query(1, 1, n, l, r);
printf("%I64d\n", ans);
}
}
return 0;
}

codeforces 446C DZY Loves Fibonacci Numbers 线段树的更多相关文章

  1. ACM学习历程—Codeforces 446C DZY Loves Fibonacci Numbers(线段树 && 数论)

    Description In mathematical terms, the sequence Fn of Fibonacci numbers is defined by the recurrence ...

  2. Codeforces 446C DZY Loves Fibonacci Numbers [线段树,数论]

    洛谷 Codeforces 思路 这题知道结论就是水题,不知道就是神仙题-- 斐波那契数有这样一个性质:\(f_{n+m}=f_{n+1}f_m+f_{n}f_{m-1}\). 至于怎么证明嘛-- 即 ...

  3. codeforces 446C DZY Loves Fibonacci Numbers(数学 or 数论+线段树)(两种方法)

    In mathematical terms, the sequence Fn of Fibonacci numbers is defined by the recurrence relation F1 ...

  4. Codeforces 446-C DZY Loves Fibonacci Numbers 同余 线段树 斐波那契数列

    C. DZY Loves Fibonacci Numbers time limit per test 4 seconds memory limit per test 256 megabytes inp ...

  5. Codeforces 446C —— DZY Loves Fibonacci Numbers(线段树)

    题目:DZY Loves Fibonacci Numbers 题意比較简单,不解释了. 尽管官方的题解也是用线段树,但还利用了二次剩余. 可是我没有想到二次剩余,然后写了个感觉非常复杂度的线段树,还是 ...

  6. codeforces 446C DZY Loves Fibonacci Numbers 数论+线段树成段更新

    DZY Loves Fibonacci Numbers Time Limit:4000MS     Memory Limit:262144KB     64bit IO Format:%I64d &a ...

  7. Codeforces 446C - DZY Loves Fibonacci Numbers(斐波那契数列+线段树)

    Codeforces 题目传送门 & 洛谷题目传送门 你可能会疑惑我为什么要写 *2400 的题的题解 首先一个很明显的想法是,看到斐波那契数列和 \(10^9+9\) 就想到通项公式,\(F ...

  8. CF446C DZY Loves Fibonacci Numbers 线段树 + 数学

    有两个性质需要知道: $1.$ 对于任意的 $f[i]=f[i-1]+f[i-2]$ 的数列,都有 $f[i]=fib[i-2]\times f[1]+fib[i-1]\times f[2]$ 其中 ...

  9. Codeforces446C DZY Loves Fibonacci Numbers(线段树 or 分块?)

    第一次看到段更斐波那契数列的,整个人都不会好了.事后看了题解才明白了一些. 首先利用二次剩余的知识,以及一些数列递推式子有下面的 至于怎么解出x^2==5(mod 10^9+9),我就不知道了,但是要 ...

随机推荐

  1. Nodejs学习(一)-Nodejs和express的安装和配置

    声明我的操作系统是ubuntu环境,直接下载了tar文件进行解压安装,步骤如下 1.nodejs官网下载node-v4.6.0-linux-x86.tar.xz文件. youyuan1980@youy ...

  2. AIX下安装bash

    在AIX系统下,默认是没有安装bash环境的,对于经常操作的维护人员来说,非常不方便,所以下面我们来动手安装bash. 1.确认系统是否已安装bash 方法1:之间敲bash命令,若提示没有此命令则没 ...

  3. 提高 ASP.NET Web 应用性能的 24 种方法和技巧

    那性能问题到底该如何解决?以下是应用系统发布前,作为 .NET 开发人员需要检查的点. 1.debug=「false」 当创建 ASP.NET Web应用程序,默认设置为「true」.开发过程中,设置 ...

  4. WEB测试方法及注意地方

    1页面部分(1) 页面清单是否完整(是否已经将所需要的页面全部都列出来了)(2) 页面是否显示(在不同分辨率下页面是否存在,在不同浏览器版本中页面是是否显示)(3) 页面在窗口中的显示是否正确.美观( ...

  5. php返回数据库查询时出现Resource id #2

    1.使用php调用MySQL数据库的过程是不是先用mysql_query(SELECT*...)或mysql_list_dbs()等查询函数返回结果指针(mysql查询函数中还有没有这样的返回指针函数 ...

  6. [转]eclipse最佳设置

    设置工作空间的项目编码, 防止出现乱码     Window - Preferences - General - Workspace     将"Text file encoding&quo ...

  7. NSDate管理日期和时间

    //时间初始化        NSDate *date = [[NSDate alloc]initWithString:@"2010-01-01 23:59:59 +0900"]; ...

  8. Python之路-Day2

    二进制 1bit = 一个二进制位 8bit = 1byte 循环 for while 数据类型 数字.字符串.列表.元祖.字典.集合 字符编码 文件处理 for循环: for i in range( ...

  9. 2016 China-Final-F题 ——(SA+二分)

    其实是一个很经典的字符串问题,但是我们比赛的时候没出. 先看一下UVA11107这题,题意是,找出最长的一个字符串,在至少一半的字符串中出现过.只要把所有的字符串用不同的分隔符分开,然后SA一下,最后 ...

  10. IOS系列swift语言之课时七

    这下需要掌握的就是类型转换,类的构造器,判断类型,异常,异常的处理,defer,范型,约束加速刷代码 import Foundation /* 类型转换 1.利用类的构造器进行转换 2.系统可能提供一 ...