Codeforces 446-C DZY Loves Fibonacci Numbers 同余 线段树 斐波那契数列
4 seconds
256 megabytes
standard input
standard output
In mathematical terms, the sequence Fn of Fibonacci numbers is defined by the recurrence relation
F1 = 1; F2 = 1; Fn = Fn - 1 + Fn - 2 (n > 2).
DZY loves Fibonacci numbers very much. Today DZY gives you an array consisting of n integers: a1, a2, ..., an. Moreover, there are m queries, each query has one of the two types:
- Format of the query "1 l r". In reply to the query, you need to add Fi - l + 1 to each element ai, where l ≤ i ≤ r.
- Format of the query "2 l r". In reply to the query you should output the value of
modulo 1000000009 (109 + 9).
Help DZY reply to all the queries.
The first line of the input contains two integers n and m (1 ≤ n, m ≤ 300000). The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 109) — initial array a.
Then, m lines follow. A single line describes a single query in the format given in the statement. It is guaranteed that for each query inequality 1 ≤ l ≤ r ≤ n holds.
For each query of the second type, print the value of the sum on a single line.
4 4
1 2 3 4
1 1 4
2 1 4
1 2 4
2 1 3
17
12
After the first query, a = [2, 3, 5, 7].
For the second query, sum = 2 + 3 + 5 + 7 = 17.
After the third query, a = [2, 4, 6, 9].
For the fourth query, sum = 2 + 4 + 6 = 12.
官方题解:
As we know, 
Fortunately, we find that 
So, 
With multiplicative inverse, we find,



Now, 
As you see, we can just maintain the sum of a Geometric progression 
This is a simple problem which can be solved with segment tree in
.
这道题是Fibonacci数列通项公式的应用,比较经典。至少我是不可能想到斐波那契数列与等比数列有任何关联。还有一点,在程序内层循环中,快速幂的时间复杂度是不容忽视的(估计是线段树写抽了),这里既然公比恒定,可先与处理一下。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define MAXN 310000
#define MAXT 1210000
#define MOD 1000000009
#define lch (now<<1)
#define rch (now<<1^1)
void nextInt(int &x)
{
char ch;
x=;
while (ch=getchar(),ch>''||ch<'');
do
x=x*+ch-'';
while (ch=getchar(),ch<=''&&ch>='');
}
int n,m;
typedef long long qword;
int num[MAXN];
qword val1,val2,val3,val4,val3_n,val4_n,mod;
qword val3_pow[MAXN],val4_pow[MAXN];
qword pow_mod(qword x,qword y,int mod)
{
qword ret=;
while (y)
{
if (y&)ret=ret*x%mod;
x=x*x%mod;
y>>=;
}
return ret;
}
struct node
{
int l,r;
qword sum;
qword inc3,inc4;
}tree[MAXT];
inline void update_sum_3(int now,int inc3)
{
qword temp;
temp=inc3*(val3_pow[tree[now].r-tree[now].l+]-)%MOD*val3_n%MOD;
// temp=(temp+MOD)%MOD;
tree[now].sum=(tree[now].sum+temp)%MOD;
}
inline void update_sum_4(int now,int inc4)
{
qword temp;
temp=inc4*(val4_pow[tree[now].r-tree[now].l+]-)%MOD*val4_n%MOD;
temp=(-temp+MOD)%MOD;
tree[now].sum=(tree[now].sum+temp)%MOD;
}
inline void down(int now)
{
if (tree[now].l==tree[now].r)
{
if (tree[now].inc3)
{
tree[now].inc3=;
}
if (tree[now].inc4)
{
tree[now].inc4=;
}
return ;
}
if (tree[now].inc3)
{
qword temp;
tree[lch].inc3=(tree[lch].inc3+tree[now].inc3)%MOD;
// tree[lch].inc3%=MOD;
update_sum_3(lch,tree[now].inc3);
tree[rch].inc3+=temp=val3_pow[tree[lch].r-tree[lch].l+]*tree[now].inc3%MOD;
tree[rch].inc3%=MOD;
update_sum_3(rch,temp);
tree[now].inc3=;
}
if (tree[now].inc4)
{
qword temp;
tree[lch].inc4+=tree[now].inc4;
tree[lch].inc4%=MOD;
update_sum_4(lch,tree[now].inc4);
tree[rch].inc4+=temp=val4_pow[tree[lch].r-tree[lch].l+]*tree[now].inc4%MOD;
tree[rch].inc4%=MOD;
update_sum_4(rch,temp);
tree[now].inc4=;
}
}
inline void update(int now)
{
if (tree[now].l!=tree[now].r)
tree[now].sum=(tree[lch].sum+tree[rch].sum)%MOD;
}
void init()
{
/*//{{{
int i;
for (i=1;i<MOD;i++)
{
if ((qword)i*i%MOD==5)
{
val1=i;
break;
}
}
cout<<val1<<endl;
for (i=1;i<MOD;i++)
{
if ((qword)i*5%MOD==val1)
{
val2=i;
break;
}
}
cout<<val2<<endl;
for (i=1;i<MOD;i++)
{
if ((qword)i*2%MOD-1==val1)
{
val3=i;
break;
}
}
cout<<val3<<endl;
for (i=1;i<MOD;i++)
{
if ((qword)i*2-1==(-val1+MOD)%MOD)
{
val4=i;
break;
}
}
cout<<val4<<endl;//}}}*/
val1=;//sqrt(5)
val2=;//sqrt(5)/5
val3=;//(1+sqrt(5))/2
val4=;//(1-sqrt(5))/2
int i;
qword temp=val3;
val3_pow[]=;
for (i=;i<MAXN;i++)
{
val3_pow[i]=val3_pow[i-]*val3%MOD;;
}
val4_pow[]=;
for (i=;i<MAXN;i++)
{
val4_pow[i]=val4_pow[i-]*val4%MOD;
}
val3_n=pow_mod(val3-,MOD-,MOD);
val4_n=pow_mod(val4-,MOD-,MOD);
//fib(n)=val2*(val3^n-val4^n);
}
void build_tree(int now,int l,int r)
{
tree[now].l=l;
tree[now].r=r;
if (l==r)
{
tree[now].sum=num[l];
return ;
}
int mid=(l+r)/;
build_tree(lch,l,mid);
build_tree(rch,mid+,r);
update(now);
}
void add_val(int now,int l,int r,int rk)
{
if (tree[now].l==l&&tree[now].r==r)
{
qword temp;
temp=val2*val3%MOD*val3_pow[rk]%MOD;
tree[now].inc3=(tree[now].inc3+temp)%MOD;
update_sum_3(now,temp);
temp=val2*val4%MOD*val4_pow[rk]%MOD;
tree[now].inc4=(tree[now].inc4+temp)%MOD;
update_sum_4(now,temp);
return ;
}
down(now);
int mid=(tree[now].l+tree[now].r)>>;
if (r<=mid)
{
add_val(lch,l,r,rk);
update(now);
return ;
}
if (mid<l)
{
add_val(rch,l,r,rk);
update(now);
return ;
}
add_val(lch,l,mid,rk);
add_val(rch,mid+,r,rk-l+mid+);
update(now);
}
//ok
qword query(int now,int l,int r)
{
if (tree[now].l==l&&tree[now].r==r)
{
return tree[now].sum;
}
down(now);
int mid=(tree[now].l+tree[now].r)>>;
if (r<=mid)
return query(lch,l,r);
if (mid<l)
return query(rch,l,r);
return (query(lch,l,mid)+query(rch,mid+,r))%MOD;
} int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
//scanf("%d%d",&n,&m);
nextInt(n);
nextInt(m);
int i,j,k,x,y,z;
init();
for (i=;i<=n;i++)
nextInt(num[i]);
build_tree(,,n);
while (m--)
{
nextInt(x);
nextInt(y);
nextInt(z);
if (x==)
{
add_val(,y,z,);
}else
{
printf("%I64d\n",query(,y,z));
}
}
}
Codeforces 446-C DZY Loves Fibonacci Numbers 同余 线段树 斐波那契数列的更多相关文章
- [Codeforces 316E3]Summer Homework(线段树+斐波那契数列)
[Codeforces 316E3]Summer Homework(线段树+斐波那契数列) 顺便安利一下这个博客,给了我很大启发(https://gaisaiyuno.github.io/) 题面 有 ...
- 【CF446C】DZY Loves Fibonacci Numbers (线段树 + 斐波那契数列)
Description 看题戳我 给你一个序列,要求支持区间加斐波那契数列和区间求和.\(~n \leq 3 \times 10 ^ 5, ~fib_1 = fib_2 = 1~\). Solut ...
- Codeforces Round #FF 446 C. DZY Loves Fibonacci Numbers
參考:http://www.cnblogs.com/chanme/p/3843859.html 然后我看到在别人的AC的方法里还有这么一种神方法,他预先设定了一个阈值K,当当前的更新操作数j<K ...
- [CodeForces - 447E] E - DZY Loves Fibonacci Numbers
E DZY Loves Fibonacci Numbers In mathematical terms, the sequence Fn of Fibonacci numbers is define ...
- Codeforces 316E3 线段树 + 斐波那切数列 (看题解)
最关键的一点就是 f[ 0 ] * a[ 0 ] + f[ 1 ] * a[ 1 ] + ... + f[ n - 1] * a[ n - 1] f[ 1 ] * a[ 0 ] + f[ 2 ] * ...
- [莫队算法 线段树 斐波那契 暴力] Codeforces 633H Fibonacci-ish II
题目大意:给出一个长度为n的数列a. 对于一个询问lj和rj.将a[lj]到a[rj]从小到大排序后并去重.设得到的新数列为b,长度为k,求F1*b1+F2*b2+F3*b3+...+Fk*bk.当中 ...
- codeforces 446C DZY Loves Fibonacci Numbers(数学 or 数论+线段树)(两种方法)
In mathematical terms, the sequence Fn of Fibonacci numbers is defined by the recurrence relation F1 ...
- 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 数论+线段树成段更新
DZY Loves Fibonacci Numbers Time Limit:4000MS Memory Limit:262144KB 64bit IO Format:%I64d &a ...
随机推荐
- CentOS Nginx+jdk+tomcat 环境搭建
一.jdk安装 jdk下载地址:http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloa ...
- WCF学习心得--客户端获取服务端自定义类数据
因项目需求,需要一个WCF服务,赶鸭子上架吧!下面直接切入正题! 首先创建WCF应用程序,具体如何创建就不赘述了,网上一大篇,我主要说说自己遇到的问题 问题一:超时问题,在最后获取数据的时候突然提示服 ...
- [置顶] Linux下的截图小工具
Linux下的截图工具scrot 基于命令行 先下载:scrot apt-get install scrot 对该工具的操作: 分为以下几个部分 1.抓取整个桌面 scrot pic.jpg 2.抓取 ...
- [转]开源应用架构之asterisk
作者:Russell Bryant 翻译:jiazhengfeng Asterisk[1]是一款GPLv2协议下的开源电话应用平台.简单来说,Asterisk是一个服务器应用,能够完成发起电话呼叫.接 ...
- thinkphp中session跨域问题
问题描述 <thinkphp实现短信验证注册>中,小编不止记录了短信验证码的实现方法,同时还记录了图片验证码的实现方法. 本地使用,一切正常:后端项目和前端项目都部署到服务器,一切正常:后 ...
- 源码解析之–YYAsyncLayer异步绘制
来源:伯乐在线专栏作者 - Shelin 链接:http://ios.jobbole.com/86878/ 点击 → 了解如何加入专栏作者 前言 YYAsyncLayer是异步绘制与显示的工具.最初是 ...
- SDWebImage 原理及使用
这个类库提供一个UIImageView类别以支持加载来自网络的远程图片.具有缓存管理.异步下载.同一个URL下载次数控制和优化等特征. SDWebImage 加载图片的流程 入口 setImageWi ...
- ASP.NET性能优化之分布式Session
如果我们正在使用Session,那么构建高性能可扩展的ASP.NET网站,就必须解决分布式Session的架构,因为单服务器的SESSION处理能力会很快出现性能瓶颈,这类问题也被称之为Session ...
- XPath操作XML文档
NET框架下的Sytem.Xml.XPath命名空间提供了一系列的类,允许应用XPath数据模式查询和展示XML文档数据. 3.1XPath介绍 主要的目的是在xml1.0和1.1文档节点树种定位节点 ...
- SqlSugar常用增删改操作
一.添加数据 特别说明: 1.特别说明:对于自增长列的表插入数据后,当前自增长列的字段,仍旧为0,但可以通过Insert方法的返回值来获取 SqlSugarClient db = SugarConte ...