FZOJ P2109 卡德加的兔子

2022-09-06 10:03:10 字數 2865 閱讀 3475

卡德加喜歡養兔子。他在達拉然的下水道裡放了 $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

254

8916121

2017 年 noip 夏令營

看到了詢問區間,馬上想到線段樹;看到了斐波那契數列,馬上想到矩陣快速冪。問題在於怎麼結合了。

對於兩個數列,如果這兩個數列都具有斐波那契性質,則這兩個數列的和也具有斐波那契性質。

什麼意思呢?就是說對於兩個數列 $\$,$\$,如果 $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=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$ 演算法可知,此題還有乙個優化:

斐波那契數列對 $10007$ 取模時,第 $1$ 個數與第 $20017$ 個數是一樣的,第 $2$ 個數與第 $20018$ 個數是一樣的。

這樣就可以預先算好 $20017$ 個矩陣的值了,不需要使用快速冪。

**如下:

1 #include 2 #include 3 #include 4

using

namespace

std;56

struct

matrix 9};

1011

const

int maxn = 100000 + 5;12

const

int mod = 10007;13

14int

n, m;

15matrix one, fibo, zero;

16int l[maxn * 4], r[maxn * 4

];17 matrix sum[maxn * 4], tag[maxn * 4

];18

19 inline matrix operator +(matrix a, matrix b)

2526 inline matrix operator *(matrix a, matrix b)

32return

c;33}34

35 inline matrix operator ^ (matrix low, int

high)

43return

ans;44}

4546 inline int

read()

5253 inline void push_up(int i)

5455 inline void push_down(int

i) 64

65void build_tree(int l, int r, int

i) 72

int mid = l[i] + r[i] >> 1

;73 build_tree(l, mid, i << 1

);74 build_tree(mid + 1, r, i << 1 | 1

);75

push_up(i);76}

7778

void update_tree(int l, int r, int k, int

i) 84

push_down(i);

8586

int mid = l[i] + r[i] >> 1;87

if (r <= mid) update_tree(l, r, k, i << 1

);88

else

if (l > mid) update_tree(l, r, k, i << 1 | 1

);89

else

93push_up(i);94}

9596 matrix query_tree(int l, int r, int

i) 108

}109

110int

main() else

124 update_tree(l, r, k, 1

);125

}126

127return0;

128 }

view code

演算法筆記習題2 10

你的任務是計算a b。這是為了acm初學者專門設計的題目。你肯定發現還有其他題目跟這道題的標題類似,這些問題也都是專門為初學者提供的。輸入包含一系列的a和b對,通過空格隔開。一對a和b佔一行。對於輸入的每對a和b,你需要依次輸出a b的和。如對於輸入中的第二對a和b,在輸出中它們的和應該也在第二行。...

2 10進製數轉換

題目 每組輸入兩個數 n,m,中間空格隔開。n代表數值,m代表數制 2進製,10進製 多組輸入,遇n和m等於0結束。樣例輸入 10 2 10 10 0 0 樣例輸出 2 1010 1000 0000 1111 1111 128 255 1000 000 1111 111 64 127 思路 十進位制...

2 10 TreeView 控制項

u 本節學習目標 n了解treeview控制項的屬性及方法 n 掌握treeview控制項中加入子節點兄弟節點,刪除節點,展開所有節點,展開選定節點的下一級節點,摺疊所有節點的基本方法 n 掌握contentmenustrip控制項在treeview控制項中的應用 n學習treeview控制項綜合開...