FZOJ P2109 【卡德加的兔子】
题目描述
卡德加喜欢养兔子。他在达拉然的下水道里放了 $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 【卡德加的兔子】的更多相关文章
- BZOJ 1001: [BeiJing2006]狼抓兔子
1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 20029 Solved: 4957[Submit][ ...
- JS循环语句作业讲解(折纸、兔子生兔子、买东西组合)
1.一张纸的厚度是0.0001米,将纸对折,对折多少次厚度超过珠峰高度8848米: varn = 0;varg = 0.0001;while(){ g= g *2; n++ (g>8848bre ...
- bzoj 1001狼抓兔子(对偶图+最短路)最大流
推荐文章:<浅析最大最小定理在信息学竞赛中的应用>--周冬 题目 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的, 而且现在的兔子还 ...
- BZOJ1001: [BeiJing2006]狼抓兔子 [最小割 | 对偶图+spfa]
1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 19528 Solved: 4818[Submit][ ...
- Java程序设计之裴波拉切那数列(兔子一年的数量)
题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 1.程序分析: 兔子的规律为数列1,1,2,3,5 ...
- [BZOJ4027][HEOI2015] 兔子与樱花
Description 很久很久之前,森林里住着一群兔子.有一天,兔子们突然决定要去看樱花.兔子们所在森林里的樱花树很特殊.樱花树由n个树枝分叉点组成,编号从0到n-1,这n个分叉点由n-1个树枝连接 ...
- js 斐波那契数列(兔子问题)
对于JS初学者来说,斐波那契数列一直是个头疼的问题,总是理不清思路. 希望看完这篇文章之后会对你有帮助. 什么是斐波那契数列 : 答: 斐波那契数列,又称黄金分割数列.因数学家列昂纳多·斐波那契(Le ...
- Java经典兔子问题
题目:古典问题:3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 分析:首先我们要明白题目的意思指的是每个月的兔子总对数:假设将兔子分为小 ...
- while做法1.兔子生兔子 2.求100以内质数的和3.洗发水15元 牙膏5元 香皂2元 150元的算法
1.兔子生兔子 2.求100以内质数的和 3.150块钱花完问题
随机推荐
- hive 元数据库表描述
元数据库表描述 这一节描述hive元数据库中比较重要的一些表的作用,随着后续对hive的使用逐渐补充更多的内容. mysql元数据库hive中的表: 表名 作用 BUCKETING_COLS 存储bu ...
- 爬虫IP代理中的http与https
之前使用代理IP,构造的proxies一直都是http模式 proxies={"http": "http://{}".format(ip)} 但是今天遇到的网站 ...
- HTML、CSS知识点,面试开发都会需要--No.7 数据列表
No.7 数据列表 1.无序列表Unordered List 无序列表用block-level元素ul(unordered list)表示,每个item单独使用li(list)标记.如下代码所示: & ...
- 找不到 main 方法, 请将 main 方法定义为: public static void main(String[] args) 否则 JavaFX 应用程序类必须扩展javafx.应用程序类必 须扩展javafx.application.Application”
用eclipse写代码的时候,写了一个简单的程序,编译的时候突然出现“错误: 在类 com.test.demo 中找不到 main 方法, 请将 main 方法定义为: public static v ...
- Java图片合并
/** * 纵向合并图片,ossObject.getObjectContent()返回InputStream对象 */ private BufferedImage mergeImage(List< ...
- Robot Framework自动化测试Selenium2Library库详细用法
一.浏览器驱动 通过不同的浏览器执行脚本. Open Browser Htpp://www.xxx.com chrome 浏览器对应的关键字: firefox FireFox ff internete ...
- 项目实战02:nginx 反向代理负载均衡、动静分离和缓存的实现
目录 实验一:实现反向代理负载均衡且动静分离 1.环境准备: 2.下载编译安装tengine 3.设置代理服务器的配置文件 4.启动tengine服务 5.开启后端的web服务 6.测试 实验二:ng ...
- LeetCode 237 Delete Node in a Linked List 解题报告
题目要求 Write a function to delete a node (except the tail) in a singly linked list, given only access ...
- 快速搭建完整zabbix3.4
一.准备工作OS:centos7.4Zabbix version:3.4.6(2018/1/15日上线的新版本)Database:MariaDB关闭防火墙:systemctl stop firewal ...
- Please run SwitchHosts! as an Administrator 原因
github 访问慢的初期,不得已修改host,但直接修改host的文件太不够灵活了,使用switchhost工具. win10 遇到上述问题如这个地址 要撞墙了. 解决方法: 进入 C:\Windo ...