STEP4
2012/08/20 快樂暑假營
1 輾轉相除法
1.1 目的
求出兩正整數 α、β 的最大公因數 gcd(α, β)。 1.2 原理
給定兩個正整數 α、β (α ≥ β),令 γ 為 α 除以 β 的餘數,則 α = κβ +γ, 其中 κ 為整數。則 gcd(α, β) = gcd(γ, β)。如此可以再將 β、γ 代替原本的 α、 β 再運算,其最大公因數也不會改變。如此循環到最後,若其中一數變成 0,則 另一數則為原欲求的最大公因數 (因為 gcd(α,0) = α)。
最小公倍數可利用以下性質求得:lcm(α, β)gcd(α, β) = αβ。 Algorithm 1 GCD
1: function JizzCD(α, β)
2: if α < β then
3: Swap(α, β)
4: end if
5: if β = 0 then
6: return α
7: end if
8: γ ← α mod β
9: return JizzCD(β, γ)
10: end function
時間複雜度:O(lg(max(α, β))) 1.3 二元一次方程式
輾轉相除法也能用來求方程式 αx+ βy = gcd(α, β) 的整數解。
算法:
將 1α+ 0β = α 與 0α + 1β = β 兩個元素作輾轉相除法,到最後等式右邊會 變成 gcd(α, β),等式左邊的係數即為 x、y 的解。
Algorithm 2 Solve Linear Equation
1: function IntSolution(α, β)
2: if α = β then
3: return (0,1)
4: end if
5: (ξ, η) ← IntSolution(β, α mod β)
6: τ ←α/β
7: return (η, ξ −τ ×η)
8: end function
時間複雜度:O(lg(max(α, β)))
2 質數
2.1 質數檢查
一個合數 N 不可能沒有 ≤√
N 的因數。將所有 1∼ √
N 的質數一個一個拿 來除以 N,若皆不能整除,代表 N 為質數。
時間複雜度:O(√ N)
2.2 質數篩法
目的:判斷 1∼ N 中有哪些質數。
A__A 算法
把 1 ∼N 的每一個數,都用上述方法判斷是否為質數。
時間複雜度:O(N√
N) (Q__Q)
快速篩法
先建立一個 1∼ N 的表,記錄每個數有沒有可能是質數。
首先把 1 刪掉。接著找出最小的還沒刪的數 (目前來說是 2),把所有 2 的倍數 都刪掉。此時再找最小還沒刪的數 (3),把所有 3 的倍數都刪掉,再找最小還沒
刪的數 (5)…這樣下去,刪到 √
N 為止。餘下的所有還沒被刪的數皆為質數。
優化:事實上選 κ 的倍數來刪的時候,κ2 以下的數,必定有其他更小的質因
時間複雜度:O(N lg lgN) ≈O(N) 2.3 質因數分解
將一正整數 N 分解成多個相異質數的冪次相乘的形式:
N = pe11pe22· · ·pekk
算法
先建立 1 ∼ N 的質數表,由最小的開始除 N,直到除不盡時就換一個。所 有質數都除完後,若 N 還沒被除成 1,而還有剩下一個數,則那個數也是一個 質因數。(若 N 很小,為了方便,可以直接把所有 √
N 以下的數都拿來除) 時間複雜度:O(√
N)
2.4 正因數
若 N 的質因數分解為:
N = pe11pe22· · ·pekk 則其正因數個數為
(e1 + 1)(e2 + 1)· · ·(ek+ 1) 而正因數總和為
(1 +p1 + · · ·+ pe11)(1 +p2 +· · ·+pe22)· · ·(1 +pk +· · ·+pekk)
2.5 質數的性質 對於任一質數 ρ:
1. (ρ−1)! ≡ −1 (mod ρ)
2. (費馬小定理)αρ−1 ≡1 (mod ρ)
3. 對於質數 ρ > 2,1∼ ρ 的整數平方中,只有 12,(ρ−1)2 ≡ 1 (mod ρ)。取 一整數 ξ 的平方,計算 ξ2 mod ρ,可判斷 ρ 是否為質數 (有時會有例外!
所以要取多一點 ξ 值取得錯誤的機率減小)。
3 同餘
3.1 定義
若整數 α、β 符合 α = β + κµ(其中 κ 為整數,µ 為正整數),即 α 與 β 除 以 µ 的餘數相同,則稱 α ≡ β (mod µ)。
3.2 模運算
1. α ≡ β (mod µ), γ ≡ δ (mod µ) =⇒α ±β ≡ γ ±δ (mod µ) 2. α ≡ β (mod µ), γ ≡ δ (mod µ) =⇒αγ ≡ βδ (mod µ)
3. αγ ≡βγ (mod µ) =⇒ α ≡ β (mod gcd(γ,µ)µ ) 4. α ≡ β (mod µ) =⇒ ακ ≡ βκ (mod µ)
3.3 模逆元
若整數 ξ 滿足 αξ ≡ 1 (mod µ),則稱 ξ 為 α 模 µ 的模逆元,記作 ξ = α−1。 若 α 與 µ 互質,則:
αβ ≡ γ (mod µ) =⇒β ≡γα−1 (mod µ) 3.4 模逆元計算方法
1. 以輾轉相除法解 αx+µy = 1,得到 αx≡ 1 (mod µ),即 x = α−1。 時間複雜度:O(lg(µ))
2. 若 µ 為質數,由費馬小定理 αµ−1 ≡1 (mod µ) ⇒ α−1 ≡ αµ−2 (mod µ)。 時間複雜度:O(µ) (?) O(lgµ)
3.5 快速冪
上面提到模逆元的第 2 種計算方式,需要計算 αµ−2,如果 µ 很大的時候,
計算將會非常耗時。有一種簡化計算方式:
要計算 αω (mod µ),先把 α, α2, α4,· · · , α⌊lgω⌋ (mod µ) 計算出來 (一直平方即 可),然後將 ω 表示成相應的二進位值,以剛才計算好的次方湊出 ω。
時間複雜度:O(lgω) Ex: 計算 313 (mod 11)
先算出 31 ≡ 3,32 ≡ 9,34 ≡ 4,38 ≡ 5 (mod 11),以及 13 = 23 + 22 + 20 = 8 + 4 + 1。
所以 313 = 38 ×34 ×31 ≡ 5×4×3≡ 5 (mod 11)。
3.6 同餘的運用
在資訊的題目中,經常出現答案 ζ 非常大的狀況 (Ex: ζ = 10105 的數量級),
不可能將數字 ζ 直接表示出來,此時題目多會要求你輸出答案 ζ mod µ 的餘 數 (此處 µ 通常是一個很大的質數,常為 1000000007)。這時候就需要運用模運
1: function FastExp(α, β, µ)
2: τ ←α
3: Ω ← 1
4: while β > 0 do
5: if β&1 then
6: Ω ←(Ω ×τ) mod µ
7: end if
8: β ← β ≫1
9: τ ←τ2 mod µ
10: end while
11: return Ω
12: end function
13: function ModRev(α, µ)
14: return FastExp(α, µ−2, µ)
15: end function
算的四則運算,取代整數的四則運算。
Ex: 計算 123456! (mod 1000000007)。
4 組合
4.1 基本性質
資訊領域中,也常常需要計算達成某件事的方法數,就要以組合方法計算。
1. 加法原理:兩個互相獨立 (互不影響) 的選擇,只能選其中一邊中的一種,
其總方法數為兩者相加。
2. 乘法原理:兩個互相獨立 (互不影響) 的選擇,兩邊各要選一種,其總方法 數為兩者相乘。
3. 階乘:ν! = 1×2×3× · · · ×(ν −1)×ν (同時也是 ν 個相異物排列成不同 順序的方法數)。
4. 排列數 Pνµ:µ 個相異物,選其中 ν 個來排 (順序有差) 的方法數。
5. 組合數 Cνµ:µ 個相異物,選其中 ν 個出來 (順序不計) 的方法數,同時也 是 ν 個 A 物和 µ 個 B 物排成一列 (順序有差) 的方法數。
6. 重覆組合 Hνµ = Cνµ−ν+1:µ 種不同的東西無限供應,總共選 ν 個出來 (可 以重覆,順序不計) 的方法數。同時也是方程式 x1+x2+x3+· · ·+xµ = ν 的非負整數解組數。
7. 二項式定理:二項式展開的係數為組合數。
(α+β)ν =
∑ν κ=0
Cκναν−κβκ
8. 巴斯卡定理:Cνµ = Cνµ−1 + Cνµ−−11。
9. 排容原理:所有東西聯集 = 任 1 個東西交集和 − 任 2 個南北交集和 + 任 3 個東西交集和…
10. 鴿籠原理:把 χ 個東西放到 θ 個箱子,至少會有一個箱子數量 ≥ ⌈χθ⌉ 由以上幾點可知,排列組合計算出來的方法數,經常會遠超過 int 的範圍,需 要配合前面的模運算。
4.2 遞迴
有時候我們並沒有辦法直接計算一個數列中某項的值,但是我們可以得到數 列中任一項與前後幾項的關係,稱為遞迴式。
Ex: 梗賤 橋上的第 i 個木板重 σi 公斤,你想知道第 30 塊木板有多重,但由 於梗賤 過於猥瑣,導致你不敢走上去,你只知道梗賤 橋上的第一塊木板重 1 公 斤,之後每一塊木塊都是前一塊的 2 倍多 1 公斤。這時可以列出遞迴式:
σi+1 = 2σi + 1
於是你可以由第 1 塊木板的重量計算第 2 塊木板的重量,再計算第 3 塊,一 直下去,最後得到第 30 塊木板的重量。
梗賤:嘻嘻嘻!偷偷跟你說喔,梗賤 橋總共有 123 億塊木板,你知道最後一 塊木板到底有多重嗎 XDDDDD
這個時候你發現了一件神奇的事:如果你把每塊木板的重量都加一的話…
σi+1 + 1 = 2(σi + 1)
σn+ 1 = 2n−1(σ1 + 1) = 2n−1 ×2 σn = 2n −1
這樣的式子稱為遞迴式的一般式,只要帶數字進去,馬上可以求得第 n 項的 值。但很多遞迴式是解不出這種簡單的一般式來的,還是只好學梗賤 一樣一個
一個有名的遞迴式:
F1 = 1, F2 = 1, Fi = Fi−1 + Fi−2
解出來的前幾項分別為:1,1,2,3,5,8,13,21,· · ·,即為費氏數列。
事實上,遞迴式在 DP 中扮演很重要的角色,這部份將在下週 DP 課程中說 明。
5 矩陣
5.1 定義
一堆數字排成長方形,加上中括號。(?)
m×n 的矩陣代表這個矩陣有 m 列,n 欄。例如以下為一個 5×8 的矩陣:
α β γ δ ϵ ε ζ η θ ϑ ι κ λ µ ν ξ π ϖ ρ ϱ σ ς τ υ ϕ φ χ ψ ω Γ ∆ Θ Λ Ξ Π Σ Υ Φ Ψ Ω
一個 m×n 的矩陣可以表示成:
Am×n =
A11 A12 · · · A1n A21 A22 · · · A2n
... ... ... ...
Am1 Am2 · · · Amn
= [
Aij
]
m×n
一個矩陣通常使用二維陣列來儲存:A[i][j] = Aij
5.2 意義
阿不就是一些數字排得很整齊而已嘛 (誤)
矩陣實際上是一種「操作」(詳情請見 Linear Algebra)。
5.3 基本運算
由於矩陣的操作意義特性,需要遵守特定的運算規則。
1. 加法:[Aij]m×n+ [Bij]m×n = [Aij +Bij]m×n (各元素直接相加,注意矩陣大 小需相同)
2. 係數乘矩陣:γ[Aij]m×n = [γAij]m×n (每個元素都乘以係數)
3. 矩陣乘矩陣:[Aik]m×n[Bkj]n×p = [Cij]m×p = [∑nk=1Aik ×Bkj]m×p
數學形式可能有點難以理解,簡單來說就是把左矩陣的第 i 橫排和右矩陣 的第 j 直列,對應的元素一一乘起來,就變成新矩陣的第 (i, j) 元素。
· · · · Ai1 Ai2 · · · Ain
· · · ·
· · · ·
×
... ... B1j ...
... ... B2j ...
... ... ... ...
... ... Bnj ...
=
. .. ... ... ...
. .. ... Cij . ..
. .. ... ... ...
. .. ... ... ...
AB = C, Cij = Ai1B1j +Ai2B2j +· · ·+AijBnj
Ex: 2×2 矩陣乘法:
[1 2 3 4
] [2 5 4 3 ]
=
[1×2 + 2×4 1×5 + 2×3 3×2 + 4×4 3×5 + 4×3 ]
=
[10 11 22 27 ]
注意:並不是任意兩個矩乘都可以相乘!只有左矩陣的寬與右矩陣的高相
等 (以上代號中的 n) 時,才可以相乘。
而且矩陣乘法不存在交換律,即 AB ̸= BA!!
時間複雜度:對於兩個 N ×N 的矩陣相乘,O(N3)
4. 單位矩陣:N ×N 的單位矩陣 IN,只有對角線上的數字為 1,其他為 0。
1 0 · · · 0 0 1 · · · 0 ... ... ... ...
0 0 · · · 1
對於任何可與 I 相乘的矩陣 A、B,皆有 AI = A, IB = B,性質類似代 數乘法運算中的「1」。
5. 矩陣冪次:咦不是說矩陣乘法沒有交換律嗎?但是如果自己乘自己的話,
是可以交換的!(廢話,交換了等於沒交換 XDD)
所以可以定義矩陣的冪次:AN = AAAA· · ·A (N 個 A)
計算方法可比照前面整數運算的快速冪,在 O(lgN) 時間內完成。(其實這 就是矩陣在資訊題目中最好用的地方之一!)
6. 反矩陣:若 AA−1 = A−1A = I,則稱 A−1 為 A 的反矩陣。只有正方形矩 陣才可能有反矩陣,而且還不一定有。
計算方式:高斯消去法,計算方式與解 N 元一次聯立方程組的方法相同。
(這部份以後會再討論)
min 函數之類的),且每一次的遞迴式都相同,則可以利用矩陣來加速。
首先要將遞迴式轉成矩陣形式,然後使用矩陣的快速冪來加速。
Ex: 費氏數列 Fi = Fi−1 +Fi−2
於是,我們需要構造一個矩陣,將數對 (Fi, Fi−1) 轉移到 (Fi+1, Fi)。由費 氏數列的遞迴式,我們可以寫出聯立方程組:
{ Fi+1 = Fi + Fi−1 Fi = Fi + 0
寫成矩陣形式的遞迴式:
[Fi+1 Fi
]
=
[1 1 1 0
] [ Fi Fi−1
]
因此, [
FN FN−1
]
=
[1 1 1 0
]N−1[ F1 F0
]
先用快速冪把轉移矩陣的 N − 1 次方算出來,再乘以初始矩陣 (F1 = 1, F0 = 0),即可得到 FN 的值。
時間複雜度:O(lgN) (注意到直接由小算到大的算法為 O(N))
6 Exercise
1. 證明輾轉相除法的時間複雜度為 O(lgΞ),其中 Ξ 為數字中較大的那個。
(放心,這不是上次的題單 XDD)
2. 求在 [λ, γ] 中有幾個數 Φ 是質數。O (√
Φ + (γ −λ) )
3. 有一個神奇觸手,一開始是 (α) 的,接者每天 (α) 會變成 (β),而 (β) 會 變成 (β)(α),求第 Ω 天由左往右第 Γ 個觸手是什麼。
4. 有個數學老師出了一個非常難算的高次方程組,但他居然忘記答案了(慘),
給妳這個 N 元 M 次方程式,請你幫他解回來。(N3M ≤ 108)
5. 有 Ψ 個鍋子,兩個鍋子上可能有筷子相通,有隻螞蟻從某個起點開始爬,
他爬到與某個鍋子相鄰的所有鍋子機率相等,問 Θ 步後處在某個鍋子的機 率。O(Ψ3lgΘ)
6. 有 Λ 個人站成一列,每個人有一個 0∼ 9 的數字,最多能挑多少人依原本 順序站成一排形成一個新的數且和 ϵ 互質。O(Λϵ)
7. 給你 ϕ 個數 ξi,問你能 XOR 出最大的值。
8. 求 for ( unsigned int i = A ; i ! = B ; i = (i+C)%(1 ≪ K) ) { J1ZZZZ();
} 會讓你 J1ZZZZ() 幾次。
9. (本次模擬賽 pB 0005) 梗賤 橋上有 N 塊木板,會移來移去,問你要怎樣
才不會掉到 18 層地獄見梗賤。O(N18)
10. (本次模擬賽 pH 0011) 有 N 個亂數 (機率不一定均勻分布),一次給你看一
個,你要立刻決定選或不選,決定了才能看下一個,然後全部 N 個數要選 一個,問你要怎樣才能讓選到最大值的機率最大。O(?)