upc 卡德加的兔子 线段树 + 矩阵快速幂

卡德加的兔子
时间限制: 5 Sec 内存限制: 128 MB

题目描述
卡德加喜欢养兔⼦。他在达拉然的下⽔道⾥放了N个兔笼(编号1到N),⾥⾯养着他从德拉诺带来的兔⼦。它们的繁殖遵循斐波那契数列的规律:刚开始时,笼⼦⾥有⼀对刚出⽣的兔⼦。每对兔⼦在出⽣第⼆个⽉后,每个⽉都⽣⼀对兔⼦。(第⼀个⽉结束后有1对兔⼦。第⼆个⽉结束后有2对。)
卡德加从苏拉玛的⼤魔导⼠艾利桑德那边学习了先进的扭曲时空法术。
有时候,他会对⼀排连续的兔笼(从第L号到第R号)释放时光流逝法术,让这些兔笼⾥的时间前进K个⽉。另外⼀些时候,他想喂⼀下兔⼦,所以他想知道第L号到第R号兔笼⾥有多少只兔⼦。
(假设这些操作都是在⼀个⽉以内完成的,不需要考虑⾃然时间对兔⼦的影响。)
输入
第⼀⾏两个整数N;M,表⽰兔笼的数量和操作的数量。
接下来M⾏,每⾏包含三个数L;R;K。如果K>0,说明卡德加在使⽤时光流逝,编号L到R的兔笼时间前进K个⽉。如果K=0,说明他只是想喂兔⼦了,输出这些兔笼⾥有多少兔⼦。
输出
对每个喂兔⼦的操作,输出兔⼦的数量。答案模10007。
样例输入 Copy
100 100
26 85 0
2 81 1
67 69 0
22 69 2
27 80 0
79 87 2
57 63 2
76 80 3
95 99 4
45 94 2
27 75 1
22 75 0
12 51 2
25 66 2
11 61 1
83 88 0
27 83 1
14 97 1
71 90 3
10 44 4
73 93 4
1 98 4
23 93 3
56 76 3
13 25 2
57 68 1
18 28 3
19 28 0
21 78 4
10 95 3
93 98 4
73 81 0
28 44 0
20 53 0
59 75 4
53 69 2
9 54 1
55 95 4
14 46 4
22 50 2
35 98 3
34 93 4
91 92 4
43 53 2
45 64 2
58 87 4
64 74 3
36 62 4
16 98 0
71 76 3
39 99 1
6 16 3
12 73 2
37 82 4
56 92 1
81 99 0
9 51 3
27 80 4
13 60 3
24 39 0
13 17 1
46 54 0
81 84 4
45 61 1
21 87 0
12 61 1
52 98 0
25 64 2
3 68 0
61 64 0
24 45 4
16 53 2
23 59 3
68 86 4
55 74 1
68 74 4
22 87 1
5 21 1
3 89 1
5 84 2
18 58 1
47 81 3
74 80 1
54 71 0
9 16 2
29 55 4
12 85 1
49 84 0
30 71 3
50 51 0
51 51 0
2 38 0
14 92 3
5 31 1
5 53 1
34 83 1
29 69 0
34 82 2
50 93 1
83 96 2
样例输出 Copy
60
3
140
607
27
6408
1161
5444
7985
9779
9274
5261
9934
2118
9996
4133
2687
6932
7982
3829
2931
3078
8342
提示

首先要做这个题,需要用矩阵快速幂来求第 n 项的斐波那契数列,因为矩阵乘法是有分配律的,所以当前进 k 天,也就是 { 1 , 1 }{ 1 , 0 } 的 k 次方 乘上原来线段树维护的矩阵值,以及懒标记的值,那么这个题就转换成了区间乘法了,唯一需要的一点就是掏出来个好的矩阵板子,以前没有存矩阵的板子,光这个板子就卡了我半天。
注意一下懒标的初始值设为 单位矩阵,区间和 设位 fib2矩阵({ 1 , 0 }{ 0 , 0 }) ,mp[ 0 ] [ 0 ]这个位置就是斐波那契的第1项,因为题意可知初始的时候都应该是第一项。
pushdown的时候注意 哪个矩阵乘上哪个矩阵,矩阵乘法是没有交换律的,乘反了答案肯定是不对的。
套上板子之后,心情就变得愉悦起来了 ~
一开始还想用斐波那契数列模数有循环节打个表来做,结果这样的方法只能支持单点修改,修改一个区间是不现实的。。
改下代码,尽量变得可读性高一点吧,写的太丑了。。

#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
using namespace std;

typedef long long LL;
typedef pair<int,int> PII;

const int N=100010,M=2,mod=10007,INF=0x3f3f3f3f;
const double eps=1e-6;

struct Mat
{
   
    int r,c,mp[5][5];
    Mat(){
    memset(mp,
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值