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]$
其中 $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 线段树 + 数学的更多相关文章
- ACM学习历程—Codeforces 446C DZY Loves Fibonacci Numbers(线段树 && 数论)
Description In mathematical terms, the sequence Fn of Fibonacci numbers is defined by the recurrence ...
- 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. ...
- Codeforces 446C DZY Loves Fibonacci Numbers [线段树,数论]
洛谷 Codeforces 思路 这题知道结论就是水题,不知道就是神仙题-- 斐波那契数有这样一个性质:\(f_{n+m}=f_{n+1}f_m+f_{n}f_{m-1}\). 至于怎么证明嘛-- 即 ...
- Codeforces446C DZY Loves Fibonacci Numbers(线段树 or 分块?)
第一次看到段更斐波那契数列的,整个人都不会好了.事后看了题解才明白了一些. 首先利用二次剩余的知识,以及一些数列递推式子有下面的 至于怎么解出x^2==5(mod 10^9+9),我就不知道了,但是要 ...
- 【思维题 线段树】cf446C. DZY Loves Fibonacci Numbers
我这种maintain写法好zz.考试时获得了40pts的RE好成绩 In mathematical terms, the sequence Fn of Fibonacci numbers is de ...
- cf446C DZY Loves Fibonacci Numbers
C. DZY Loves Fibonacci Numbers time limit per test 4 seconds memory limit per test 256 megabytes inp ...
- codeforces 446C DZY Loves Fibonacci Numbers(数学 or 数论+线段树)(两种方法)
In mathematical terms, the sequence Fn of Fibonacci numbers is defined by the recurrence relation F1 ...
- 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 ...
- Codeforces 446C —— DZY Loves Fibonacci Numbers(线段树)
题目:DZY Loves Fibonacci Numbers 题意比較简单,不解释了. 尽管官方的题解也是用线段树,但还利用了二次剩余. 可是我没有想到二次剩余,然后写了个感觉非常复杂度的线段树,还是 ...
随机推荐
- IP核——PLL
一.Quartus II创建PLL 1.打开Quartus ii,点击Tools---MegaWizard Plug-In Manager 2.弹出创建页面,选择Creat a new custom ...
- PKUSC2019题解
$D1T1$:$n$个村庄,第$i$个村庄的人要去第$p_i$个村庄(保证$p_i$为排列),每次可以将相邻两个村庄的人位置交换直到所有人都到达目的地.再给定一个长为$n-1$的排列$a$,表示第$i ...
- 二分法在JavaScript中的应用实例
前言:原来一直对算法和数据结构望而却步,总觉得前端可能对这块要求不用那么高,但是随着开发经验的增长以及阅历的提升,发现算法和数据结构还是相当重要的,在一些复杂功能的研发中都可以看得到它们的身影.要想提 ...
- Java线程之间通讯(三)
使用wait和notify方法实现了线程间的通讯,都是Object 类的方法,java所有的对象都提供了这两个方法 1.wait和notify必须配合synchronized使用 2.wait方法释放 ...
- Bean管理学习笔记
1.BeanFactory 介绍 1.1 首先什么是Bean? 1.Bean在Spring技术中是基于组件 2.他是Spring容器管理的最基本最常见的单元.在spring的应用场合中,bean可以是 ...
- UML系列——OO Unit4分析和学期总结
一.本单元的架构设计 1.类图 第一次 第二次 2.关键方法和架构简述 总体而言是读取图的时候就完成大部分计算(完成缓存),调用查询方法时只是展示计算的结果,少部分直接计算.主要是设计了各种自己定义的 ...
- Fortify漏洞之 Log Forging(日志伪造)
继续对Fortify的漏洞进行总结,本篇主要针对 Log Forging(日志伪造)的漏洞进行总结,如下: 1.1.产生原因: 在以下情况下会发生 Log Forging 的漏洞: 1. 数据从一个不 ...
- thinkphp5中使用phpmailer实现发送邮件功能
一.开启SMTP服务(使用php发送邮件需要用到SMTP服务,这里以163邮箱的SMTP服务为例). 1.登录163邮箱,在首页上找到“设置”. 2.选择开启的服务,一般都全选,POP3/SMTP/I ...
- 一文看懂Java Worker 设计模式
Worker模式 想解决的问题 异步执行一些任务,有返回或无返回结果 使用动机 有些时候想执行一些异步任务,如异步网络通信.daemon任务,但又不想去管理这任务的生命周.这个时候可以使用Worker ...
- GCC 编译流程简介
GCC-GCC编译流程 序言 对于大多数程序员而言,大家都知道gcc是什么,但是如果不接触到linux平台下的开发,鲜有人真正了解gcc的编译流程,因为windows+IDE的开发模式简直是一条龙全套 ...