有两个性质需要知道:

$1.$ 对于任意的 $f[i]=f[i-1]+f[i-2]$ 的数列,都有 $f[i]=fib[i-2]\times f[1]+fib[i-1]\times f[2]$

其中 $fib[i]$ 为第 $i$ 项斐波那契数列.

$2$. 对于任意满足上述条件的数列,都有 $\sum_{i=1}^{n}f[i]=f[n+2]-f[2]$

$3.$ 任意两断满足上述条件的数列每一项依次叠加,依然满足 $g[i]=g[i-1]+g[i-2]$,且上述两个性质都满足.

$4.$ 任何一段斐波那契数列也满足上述所有性质.

有了上述预备知识后,再考虑这道题:

我们用线段树来维护区间和,线段树上每个节点维护 $3$ 个信息,为 $sum,f1,f2$

即节点所维护的区间和,以及该节点及线段树中区间要加上一个前两项为 $f1,f2$ 的上述递推数列.

那么,我们只需考虑如何下传标记,如何查询即可.

假设当前节点已经有了 $f1,f2$,那么将标记下传给左子树是轻松的:直接下传即可,区间和的贡献可按照上述公式 $O(1)$ 求出.

而如果要下传给右儿子的话就不能直接传了,因为右儿子区间开头的两项并不是 $f1,f2$.

而根据上述三条性质,我们知道斐波那契数列的任何一段也是斐波那契数列.

所以,直接算出右儿子的 $f1,f2$ 即 $f1\times fib[mid-l]+f2\times fib[mid-l+1]$ 与 $f1\times fib[mid-l+1]+f2\times fib[mid-l+2]$

然后还知道 $f1,f2$ 都满足叠加性,所以直接叠加到左右儿子的 $f1,f2$ 上即可.

#include <bits/stdc++.h>
#define N 400004
#define LL long long
#define lson now<<1
#define rson now<<1|1
#define setIO(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
using namespace std;
const LL mod=1000000009;
int n,m;
LL fib[N<<1],sum[N<<1];
struct node
{
LL f1,f2,sum;
int l,r,len;
}t[N<<2];
void build(int l,int r,int now)
{
t[now].l=l;
t[now].r=r;
t[now].len=r-l+1;
if(l==r) return ;
int mid=(l+r)>>1;
if(l<=mid) build(l,mid,lson);
if(r>mid) build(mid+1,r,rson);
}
void mark(int now,LL f1,LL f2)
{
(t[now].f1+=f1)%=mod;
(t[now].f2+=f2)%=mod;
(t[now].sum+=f1*fib[t[now].len]%mod+f2*fib[t[now].len+1]%mod-f2+mod)%=mod;
}
void pushup(int now)
{
t[now].sum=(t[lson].sum+t[rson].sum)%mod;
}
void pushdown(int now)
{
if(t[now].f1==0&&t[now].f2==0) return;
int mid=(t[now].l+t[now].r)>>1;
mark(lson,t[now].f1,t[now].f2);
if(t[now].r>mid)
mark(rson,t[now].f1*fib[t[lson].len-1]%mod+t[now].f2*fib[t[lson].len]%mod,t[now].f1*fib[t[lson].len]%mod+t[now].f2*fib[t[lson].len+1]%mod);
t[now].f1=t[now].f2=0;
}
void update(int l,int r,int now,int L,int R)
{
if(l>=L&&r<=R)
{
mark(now,fib[l-L+1],fib[l-L+2]);
return;
}
pushdown(now);
int mid=(l+r)>>1;
if(L<=mid) update(l,mid,lson,L,R);
if(R>mid) update(mid+1,r,rson,L,R);
pushup(now);
}
LL query(int l,int r,int now,int L,int R)
{
if(l>=L&&r<=R)
{
return t[now].sum;
}
pushdown(now);
int mid=(l+r)>>1;
LL re=0ll;
if(L<=mid) re+=query(l,mid,lson,L,R);
if(R>mid) re+=query(mid+1,r,rson,L,R);
return re%mod;
}
int main()
{
// setIO("input");
int i,j;
scanf("%d%d",&n,&m);
fib[1]=fib[2]=1;
for(i=3;i<N;++i) fib[i]=(fib[i-1]+fib[i-2])%mod;
for(i=1;i<=n;++i) scanf("%lld",&sum[i]), (sum[i]+=sum[i-1])%=mod;
build(1,n,1);
for(i=1;i<=m;++i)
{
int opt,l,r;
scanf("%d%d%d",&opt,&l,&r);
if(opt==1) update(1,n,1,l,r);
else printf("%lld\n",(query(1,n,1,l,r)+sum[r]-sum[l-1]+mod*2)%mod);
}
return 0;
}

  

CF446C 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 线段树

    假如F[1] = a, F[2] = B, F[n] = F[n - 1] + F[n - 2]. 写成矩阵表示形式可以很快发现F[n] = f[n - 1] * b + f[n - 2] * a. ...

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

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

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

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

  5. 【思维题 线段树】cf446C. DZY Loves Fibonacci Numbers

    我这种maintain写法好zz.考试时获得了40pts的RE好成绩 In mathematical terms, the sequence Fn of Fibonacci numbers is de ...

  6. cf446C DZY Loves Fibonacci Numbers

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

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

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

  8. 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 ...

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

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

随机推荐

  1. linux安装go开发环境

    1下载go wget https://studygolang.com/dl/golang/go1.12.7.linux-amd64.tar.gz执行此命令会将go1.12.7.linux-amd64. ...

  2. Linux环境python3.6.5

     安装python3.6可能使用的依赖 yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel r ...

  3. Go语言变量的初始化

    正如上一节<Go语言变量声明>中提到的 Go语言在声明变量时,自动对变量对应的内存区域进行初始化操作.每个变量会初始化其类型的默认值,例如: 整型和浮点型变量的默认值为 0. 字符串变量的 ...

  4. SQL Server 索引优化 ——索引缺失

    本文我们将重点给出动态视图法发现数据库中缺失的索引.对于索引的调整和新建将不在本文阐述范围,后续将陆续分享相关经验. sys.dm_db_missing_index_details 缺失索引明细,包括 ...

  5. docker postgres 导出导入数据

    导出 -s  选项用来只导出表结构,而不会导出表中的数据 -t   选项用来指定要导出的数据库表 格式:docker exec -ti 容器名 pg_dump -U 用户名 -s -t table_n ...

  6. fiddler数据过滤功能

    设置会话过滤的菜单如下图: 1.勾选Use Filters选项表示使用过滤设置,不勾选则不使用 2.Actions:有四个选项 Run Filterset now:立即运行过滤设置: Load Fil ...

  7. ToLua Timer机制

    从一个Bug说起: 在内部试玩时发现有个任务的玩家跟随Npc逻辑挂了. telnet连接到出问题的设备上, 开始搞事情 这个跟随的逻辑是一个Timer驱动的. 这个Timer在主角创建时就会启动. 一 ...

  8. JS权威指南读书笔记(七)

    第十七章 事件处理 1 客户端JS程序采用了异步事件驱动编程模型. 2 关于事件的重要定义     a 事件类型(event type)     b 事件目标(event target) target ...

  9. php 执行大量sql语句 MySQL server has gone away

    php 设置超时时间单位秒 set_time_limit(3600);   php 设置内存限制ini_set('memory_limit', '1024M');   mysql服务端接收到的包的大小 ...

  10. Centos7修改默认启动内核

    #使用cat /boot/grub2/grub.cfg |grep menuentry  查看系统可用内核 root@Cs7-:/root> cat /boot/grub2/grub.cfg | ...