题目描述

卡德加喜欢养兔子。他在达拉然的下水道里放了 $N$ 个兔笼(编号从 $1$ 到 $N$),里面养着他从德拉诺带来的兔子。它们的繁殖遵循斐波那契数列的规律:刚开始时,笼子里有一对刚出生的兔子。每对兔子在出生第二个月后,每个月都生一对兔子。(第一个月结束后有 $1$ 对兔子。第二个月结束后有 $2$ 对。)

卡德加从苏拉玛的的大魔导师艾利桑德那边学习了先进的扭曲时空法术。有时候,他会对一排连续的兔笼(从第 $L$ 号到第 $R$ 号)释放时光流逝法术,让这些兔笼里的时间前进 $K$ 个月。另外一些时候,他想喂一下兔子,所以他想知道第 $L$ 号到第 $R$ 号兔笼里有多少只兔子。

(假设这些操作都是在一个月以内完成的,不需要考虑自然时间对兔子的影响。)

输入

第一行两个整数 $N,M$, 表示兔笼的数量和操作的数量。

接下来 $M$ 行,每行包含三个数 $L,R,K$。如果 $K > 0$,说明卡德加在使用时光流逝,编号 $L$ 到 $R$ 的兔笼时间前进 $K$ 个月。如果 $K = 0$,说明他只是想喂兔子了,输出这些兔笼里有多少兔子。

输出

对每个喂兔子的操作,输出兔子的数量。答案模 $10007$。

样例输入

10 10
1 3 2
1 1 0
2 4 0
3 5 0
4 7 3
3 5 0
1 4 0
2 7 0
1 9 4
2 10 0

样例输出

2
5
4
8
9
16
121

来源

2017 年 NOIP 夏令营

看到了询问区间,马上想到线段树;看到了斐波那契数列,马上想到矩阵快速幂。问题在于怎么结合了。

对于两个数列,如果这两个数列都具有斐波那契性质,则这两个数列的和也具有斐波那契性质。

什么意思呢?就是说对于两个数列 $\{x_1,x_2,x_3,x_4,\dots\}$,$\{y_1,y_2,y_3,y_4,\dots\}$,如果 $x_1+x_2=x_3, x_2+x_3=x_4, \dots, y_1+y_2=y_3, y_2+y_3=y_4, \dots$

如果有一个数列 $\{z_1,z_2,z_3,z_4,\dots\}$,其中 $z_1=x_1+y_1, z_2=x_2+y_2, \dots, z_k=x_k+y_k, \dots$

则有 $z_1+z_2=z_3, z_2+z_3=z_4, \dots$

这个不难证明,利用等式的性质就好了。

利用这个特性,我们可以在线段树的每个地方存储运算时的矩阵(因为满足分配率)。更新的时候,用矩阵加法就可以了。

另外,由 $\text{BSGS}$ 算法可知,此题还有一个优化:

斐波那契数列对 $10007$ 取模时,第 $1$ 个数与第 $20017$ 个数是一样的,第 $2$ 个数与第 $20018$ 个数是一样的。

这样就可以预先算好 $20017$ 个矩阵的值了,不需要使用快速幂。

代码如下:

 #include <iostream>
#include <cstdio>
#include <cstring>
using namespace std; struct Matrix {
int mat[][];
Matrix() { memset(mat, , sizeof mat); }
}; const int MaxN = + ;
const int Mod = ; int N, M;
Matrix One, Fibo, Zero;
int L[MaxN * ], R[MaxN * ];
Matrix Sum[MaxN * ], Tag[MaxN * ]; inline Matrix operator + (Matrix A, Matrix B) {
Matrix C;
for (int i = ; i < ; ++i) for (int j = ; j < ; ++j)
C.mat[i][j] = (A.mat[i][j] + B.mat[i][j]) % Mod;
return C;
} inline Matrix operator * (Matrix A, Matrix B) {
Matrix C;
for (int i = ; i < ; ++i) for (int j = ; j < ; ++j) {
for (int k = ; k < ; ++k) C.mat[i][j] += A.mat[i][k] * B.mat[k][j] % Mod;
C.mat[i][j] %= Mod;
}
return C;
} inline Matrix operator ^ (Matrix low, int high) {
Matrix ans;
ans.mat[][] = ans.mat[][] = ;
while (high) {
if (high & ) ans = ans * low;
high >>= ;
low = low * low;
}
return ans;
} inline int read() {
int x = ; char c;
do c = getchar(); while (c < '' || c > '');
do x = (x << ) + (x << ) + c - '', c = getchar(); while (c >= '' && c <= '');
return x;
} inline void Push_up(int i) { Sum[i] = Sum[i << ] + Sum[i << | ]; } inline void Push_down(int i) {
int lson = i << , rson = i << | ; Tag[lson] = Tag[lson] * Tag[i];
Sum[lson] = Sum[lson] * Tag[i];
Tag[rson] = Tag[rson] * Tag[i];
Sum[rson] = Sum[rson] * Tag[i];
Tag[i] = One;
} void Build_Tree(int l, int r, int i) {
L[i] = l, R[i] = r;
Tag[i] = One;
if (l == r) {
Sum[i].mat[][] = Sum[i].mat[][] = ;
return;
}
int mid = L[i] + R[i] >> ;
Build_Tree(l, mid, i << );
Build_Tree(mid + , r, i << | );
Push_up(i);
} void Update_Tree(int l, int r, int k, int i) {
if (L[i] == l && R[i] == r) {
Sum[i] = Sum[i] * (Fibo ^ k);
Tag[i] = Tag[i] * (Fibo ^ k);
return;
}
Push_down(i); int mid = L[i] + R[i] >> ;
if (r <= mid) Update_Tree(l, r, k, i << );
else if (l > mid) Update_Tree(l, r, k, i << | );
else {
Update_Tree(l, mid, k, i << );
Update_Tree(mid + , r, k, i << | );
}
Push_up(i);
} Matrix Query_Tree(int l, int r, int i) {
if (L[i] == l && R[i] == r)
return Sum[i];
Push_down(i); int mid = L[i] + R[i] >> ;
if (r <= mid) return Query_Tree(l, r, i << );
else if (l > mid) return Query_Tree(l, r, i << | );
else {
Matrix lc = Query_Tree(l, mid, i << ), rc = Query_Tree(mid + , r, i << | );
return lc + rc;
}
} int main() {
N = read(); M = read();
One.mat[][] = One.mat[][] = ;
Fibo.mat[][] = Fibo.mat[][] = Fibo.mat[][] = ;
Build_Tree(, N, ); Matrix res;
for (int m = ; m <= M; ++m) {
int l, r, k;
l = read(); r = read(); k = read();
if (k == ) {
res = Query_Tree(l, r, );
printf("%d\n", res.mat[][]);
} else
Update_Tree(l, r, k, );
} return ;
}

FZOJ P2109 【卡德加的兔子】的更多相关文章

  1. BZOJ 1001: [BeiJing2006]狼抓兔子

    1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 20029  Solved: 4957[Submit][ ...

  2. JS循环语句作业讲解(折纸、兔子生兔子、买东西组合)

    1.一张纸的厚度是0.0001米,将纸对折,对折多少次厚度超过珠峰高度8848米: varn = 0;varg = 0.0001;while(){ g= g *2; n++ (g>8848bre ...

  3. bzoj 1001狼抓兔子(对偶图+最短路)最大流

    推荐文章:<浅析最大最小定理在信息学竞赛中的应用>--周冬 题目 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的, 而且现在的兔子还 ...

  4. BZOJ1001: [BeiJing2006]狼抓兔子 [最小割 | 对偶图+spfa]

    1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 19528  Solved: 4818[Submit][ ...

  5. Java程序设计之裴波拉切那数列(兔子一年的数量)

    题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 1.程序分析: 兔子的规律为数列1,1,2,3,5 ...

  6. [BZOJ4027][HEOI2015] 兔子与樱花

    Description 很久很久之前,森林里住着一群兔子.有一天,兔子们突然决定要去看樱花.兔子们所在森林里的樱花树很特殊.樱花树由n个树枝分叉点组成,编号从0到n-1,这n个分叉点由n-1个树枝连接 ...

  7. js 斐波那契数列(兔子问题)

    对于JS初学者来说,斐波那契数列一直是个头疼的问题,总是理不清思路. 希望看完这篇文章之后会对你有帮助. 什么是斐波那契数列 : 答: 斐波那契数列,又称黄金分割数列.因数学家列昂纳多·斐波那契(Le ...

  8. Java经典兔子问题

    题目:古典问题:3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 分析:首先我们要明白题目的意思指的是每个月的兔子总对数:假设将兔子分为小 ...

  9. while做法1.兔子生兔子 2.求100以内质数的和3.洗发水15元 牙膏5元 香皂2元 150元的算法

    1.兔子生兔子 2.求100以内质数的和 3.150块钱花完问题

随机推荐

  1. mac shell 获取ip,自动启动文件http服务

    因为工作原因,时常有文件传输需求. rz.nc.rsync都用过,各有各的好处. 但相对的,向别处推文件时总有各种麻烦,尤其是在给同事发送文件时. 然后就想到了提供http服务. 在环境变量中定义别名 ...

  2. 记一次windows服务开发中遇到的问题

    最近在研究windows service和quartz.net,所以迅速在园子大神那里扒了一个demo,运行,安装一切顺利. 但在在App.config配置中增加了数据库连接字符串配置后,服务安装后无 ...

  3. Web开发——HTML基础(文件和网站结构)

    参考: 参考:Document and website structure 参考:使用HTML部分和大纲 目录: 1.基本部分 2.用于构造内容的HTML 编辑 2.1 主动学习:探索我们的例子的代码 ...

  4. 快速排序算法回顾 (Python实现)

    #这个也是快速排序-------------------------------------------------- def qsort(list): if list==[]: return [] ...

  5. 记一次mysql事故---纪念逝去的一上午

    虚拟机关机后第二天mysql起不来,回想一下我关机前和关机后的操作发现:关机前没关闭mysqld服务就直接init 0了,关机后将虚拟机内存由1G降到724M.笔者保证再也做过别的骚操作了. -- : ...

  6. Spring MVC原理及配置详解

    Spring MVC概述: Spring MVC是Spring提供的一个强大而灵活的web框架.借助于注解,Spring MVC提供了几乎是POJO的开发模式,使得控制器的开发和测试更加简单.这些控制 ...

  7. Django基本配置与URLconf

    what's the Django python的框架主要有:Django.Flask.Tornado Django是一个开放源代码的Web应用框架,由Python写成.它的主要特点是大而全,我们需要 ...

  8. ORACLE——count() 统计函数的使用

    SQL中用于统计的函数时:COUNT(). 针对count函数的使用做一个记录,很简单. 首先我数据库中建个表TEST,数据如下: 表中ID和NAME都是不重复的数据,HOME.TEL.PATH中存在 ...

  9. JAVA设计模式之静态代理

    首先看看什么是代理模式. 一 代理模式 使用一个代理对象将对象包装起来,然后用该代理对象来取代该对象,任何对原始对象的调用都要通过代理,代理对象决定是否以及何时调用原始对象的方法 二 静态模式 要求被 ...

  10. python爬取网易云音乐歌曲评论信息

    网易云音乐是广大网友喜闻乐见的音乐平台,区别于别的音乐平台的最大特点,除了“它比我还懂我的音乐喜好”.“小清新的界面设计”就是它独有的评论区了——————各种故事汇,各种金句频出.我们可以透过歌曲的评 ...