题目描述

卡德加有N个兔子笼,编号从1~N。刚开始每个兔子笼里有1对小兔,每个月小兔会长成大兔,之后的每个月这对大兔都会生出1对小兔。即兔子的繁殖遵循斐波那契数列的规律。
例如:第一个月1对小兔,第二个月1对大兔,第三个月1对小兔1对大兔,第四个月1对小兔2对大兔,第五个月2对小兔3对大兔……
卡德加学会了时间膜法,他可以对任意的[L,R]区间施加时间流逝K个月的膜法(如果他想要的话),使得这之中的兔子变为K个月后的景象。
卡德加有时想喂兔子,所以他需要知道任意的[L,R]区间内的兔子数量,即求出[L,R]区间内共有多少兔子,大兔和小兔都需要算上。
这些操作都是在一个月内完成的,所以不必考虑自然时间流逝对兔子的影响。

输入

第一行两个正整数N,M,表示兔子笼的数目和操作的数目。
接下来M行,每行三个整数L,R,K。如果K>0,表示卡德加想对区间[L,R]施放时间流逝K个月的膜法。如果K=0,表示卡德加想要喂兔子了,输出区间[L,R]内兔子总共有多少对。

输出

对每个喂兔子的操作,输出一行,一个数,表示兔子的对数。答案对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

题解

很显然的线段树类型题,但是操作不简单。
考虑区间[L,R]内有A只小兔,B只大兔,那么经过K个月后,会有多少只呢?
根据斐波那契数列的递推式,写出矩阵,再写出公式:
\(\begin{bmatrix}0&1\\1&1\end{bmatrix}^{K}\cdot\begin{bmatrix}A\\B\end{bmatrix}=\begin{bmatrix}A'\\B'\end{bmatrix}\)
A'和B'就是K月之后的小兔和大兔数量。
对于矩阵乘方,可以使用矩阵快速幂。之后就可以和普通的线段树一样操作。
需要注意的是,这题有点卡常,所以注意对矩阵乘法和其它细节上的常数优化。
优化①:对于2*2的小矩阵,不写结构体,不用循环,直接乘,会加快速度。
优化②:这是一个很有技巧的优化,注意到矩阵\(\begin{bmatrix}0&1\\1&1\end{bmatrix}^{20016}\)在模10007意义下等于单位矩阵,即K=K%20016对结果没有影响。根据这一点可以进行优化。这一点是如何想到的呢?首先应该想到,在模意义下,一切递推式均会重复。然后可以打表找规律,找循环节。对于斐波那契数列,有定理宣称,在模意义下,循环节长度不会超过模数的6倍。
优化③:继续在②的基础上优化,预处理出矩阵的0~20015次幂,做乘法时直接用,直接消灭了log和矩阵乘法的常数。
代码如下:

 1 #include<cstdio>
 2 #include<cstring>
 3 #define F(i,a,b) for(int i=a;i<=b;++i)
 4 #define Mod 10007//题目要求的模数
 5 #define Mod2 20016//循环节长度
 6 #define getchar() (S==TT&&(TT=(S=BB)+fread(BB,1,1<<15,stdin),TT==S)?EOF:*S++)
 7 char BB[1<<15],*S=BB,*TT=BB;//快读而已
 8 inline int I(){//快读
 9     int x=0;char c=getchar();
10     while(c<'0'||c>'9')c=getchar();
11     while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+c-'0',c=getchar();
12     return x;
13 }
14 int a1[262145],a2[262145],lazy[262145];
15 int A00[20016],A01[20016],A10[20016],A11[20016];//处理前20016次幂
16 int n,m,a,b,k,tmpa1,tmpa2;
17 inline int mo(int x){return x<Mod2?x:x-Mod2;}
18 void init(){//预处理过程
19     A00[0]=A11[0]=1, A01[0]=A10[0]=0;
20     F(i,1,20015) A00[i]=A01[i-1], A01[i]=(A00[i-1]+A01[i-1])%Mod, A10[i]=A11[i-1], A11[i]=(A10[i-1]+A11[i-1])%Mod;
21 }
22 void Mogic(int&x,int&y,int K){//对[x,y]施放时间流逝K月
23     tmpa1=(A00[K]*x+A01[K]*y)%Mod, tmpa2=(A10[K]*x+A11[K]*y)%Mod;
24     x=tmpa1, y=tmpa2;
25 }
26 inline void push_down(int l,int r,int i){
27     if(!lazy[i]) return;
28     Mogic(a1[i<<1],a2[i<<1],lazy[i]);
29     Mogic(a1[i<<1|1],a2[i<<1|1],lazy[i]);
30     lazy[i<<1]=mo(lazy[i<<1]+lazy[i]);
31     lazy[i<<1|1]=mo(lazy[i<<1|1]+lazy[i]);
32     lazy[i]=0;
33 }
34 void build(int l,int r,int i){ a1[i]=(r-l+1)%Mod; if(l<r) build(l,(l+r)>>1,i<<1), build(((l+r)>>1)+1,r,i<<1|1);}
35 void Xu(int l,int r,int i){//时间流逝
36     if(r<a||b<l) return;
37     if(a<=l&&r<=b) { Mogic(a1[i],a2[i],k); lazy[i]=mo(lazy[i]+k); return; }
38     push_down(l,r,i);
39     Xu(l,(l+r)>>1,i<<1);
40     Xu(((l+r)>>1)+1,r,i<<1|1);
41     a1[i]=(a1[i<<1]+a1[i<<1|1])%Mod;
42     a2[i]=(a2[i<<1]+a2[i<<1|1])%Mod;
43 }
44 int Feed(int l,int r,int i){//喂兔子
45     if(r<a||b<l) return 0;
46     if(a<=l&&r<=b) return (a1[i]+a2[i])%Mod;
47     push_down(l,r,i);
48     return (Feed(l,(l+r)>>1,i<<1)+Feed(((l+r)>>1)+1,r,i<<1|1))%Mod;
49 }
50 int main(){
51     init();
52     n=I(),m=I();
53     build(1,n,1);//建树
54     F(i,1,m){
55         a=I(),b=I(),k=I();
56         if(k) { if(k%=Mod2) Xu(1,n,1); }//这里如果k是20016的倍数,就不用动了
57         else printf("%d\n",Feed(1,n,1));
58     }
59     return 0;
60 }

转载于:https://www.cnblogs.com/PinkRabbit/p/7429964.html

【9018题解】2109 卡德加的兔子相关推荐

  1. 2017福建夏令营Day7(数论)

    埃匹希斯水晶 (apexis) ⼤家都知道,卡德加是⼀个神奇的法师. 有⼀天,他发现了⼀种可以作⽤在埃匹希斯⽔晶上的魔法:在左右两个 祭坛上放⼀定量的⽔晶,然后施放⼀个法术,左边⼀堆的⽔晶数量会变成原 ...

  2. 【bzoj题解】1001 狼抓兔子

    题目描述 现在小朋友们最喜欢"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:   ...

  3. [JZOJ]2109 清兵线 题解

    [JZOJ]2109 清兵线 题解 FIRST 题目大意 给你一些正整数,这些正整数为数轴上若干个点代表的数.现求:假设从原点出发,走m以内(包括m)的距离最多能够访问多少个点,输出m-每个点到达时已 ...

  4. 【题解】(图论) —— POJ 0714:兔子与星空

    总时间限制: 1000ms 内存限制: 10000kB 描述 很久很久以前,森林里住着一群兔子.兔子们无聊的时候就喜欢研究星座.如图所示,天空中已经有了n颗星星,其中有些星星有边相连.兔子们希望删除掉 ...

  5. 【BZOJ1001】狼抓兔子题解

    BZOJ1001: [BeiJing2006]狼抓兔子 Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还 ...

  6. 【题解】[BeiJing2008]狼抓兔子—BZOJ1001。

    (胡扯时间)今天炒鸡无聊就打算BZOJ开始从第一道题开始顺着打,这样未来一段时间内也就有事干了.结果发现A+B切掉后就遭遇了一个"小小"的瓶颈(真不友好. 好了说题说题.看题第一眼 ...

  7. CH138 兔子和兔子 题解报告

    题目传送门 [题目大意] 给定一个字符串$S$,有$m$次询问,每次询问给出四个整数$l1,r1,l2,r2$,判断$S[l1-r1]$是否与$S[l2-r2]$相同. [思路分析] $Hash$板子 ...

  8. 红书《题目与解读》第一章 数学 题解《ACM国际大学生程序设计竞赛题目与解读》

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 红书<题目与解读>第一章 数学 题解<ACM国际大学生程序设计竞赛题目与解读> ...

  9. 2017 ACM ICPC Asia Shenyang Regional Contest 题解(10 / 13)【每日亿题2 / 16】

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 目录 A.(2017 ICPC shenyang I)Little Boxes B.(2017 ICP ...

最新文章

  1. 杭电1597_find the nth digit
  2. mysql my.cnf key_buffer_size_mysql5.6之key_buffer_size优化设置-阿里云开发者社区
  3. php表格怎么合并单元格格式化,table标签的结构与合并单元格的实现方法
  4. 改变窗口的外观和大小
  5. Bootstrap3 Font Awesome 字体图标带动画的图标
  6. NLP任务增强:通过引入外部知识来提供额外信息
  7. 云计算:大数据时代的系统工程
  8. (1.2)mysql 索引概念
  9. TraceView 的使用
  10. MCSE 與 MCSA 升級 Windows Server 2008 之路
  11. 大华设备播放过程中设置播放速度
  12. iwebshop功能添加——邮箱邀请注册增加积分
  13. (摘自CSDN的koy0755)一步一步实现数据库到类的自动化映射(二) 类层次的设计 类的实现...
  14. 人工智能在计算机领域中的应用
  15. 奇思妙想 CSS 文字动画
  16. linux 下对SSD 进行读写测试
  17. 微信小程序用户昵称表情字符储存的方案
  18. Java字符串:getBytes() 方法
  19. 计算机网络用户名及密码如何查询,用wifi连接电脑的怎么查看宽带账号密码
  20. 记第一次露营的不完全体验及攻略

热门文章

  1. 找到所有数组中消失的数字—leetcode448
  2. 神经网络压缩之低比特量化的优劣分析
  3. 下述有关计算机网络的描述错误的是6,下述有关计算机总线的描述错误的是( ) 。...
  4. c++ 9.程序流程结构
  5. pwntools所带的函数使用方法
  6. [Jarvis OJ - PWN]——Test Your Memory
  7. java jar包冗余_paip.批处理清理java项目冗余jar的方法
  8. DOS 中for遍历文件内容
  9. WebForm编辑器的相关资源
  10. Excel打印区域设置