筆記:《挑戰程式設計競賽(第2版)》(1)
筆記:《挑戰程式設計競賽(第2版)》
遙想一年半前買的這本書,結果拖延了一個學期才看,收穫很大,不過有很多地方看不懂。最近開始準備藍橋杯(是啊,比賽不到一個星期了……),又把這本書拿出來看。
首先感覺自己之前白看了……不過後來又慢慢還能回想起來一些,又一次收穫很大。
也有比較開心的,一年前的很多完全看不懂的地方現在居然看得行雲流水。應該要歸功於自己理論背景的加深吧——自動機、組合數學、高數。
隔上一段時間回望自己,發現原來當時的自己那麼嫩。而今天能有所察覺,算是有進步吧。
不過還是有一些地方要花時間去想,把它們記下來。
Page 16 : 三角形-註腳①
本題還有
O(nlogn)
時間更高效的演算法,留給有興趣的讀者思考。
(1)先對n根棍子按長度排序,得到序列L
(2)從L中取最長的三根
- 如果能組成三角形則輸出,結束
- 否則刪除最長那根,轉(2)
這裡如果最長和兩根次長不能組成三角形,則最長那根無論如何都不能跟其它棒子組成三角形了,所以刪掉。
Page 47 : Fence Repair
作者直接給出來了要用Huffman樹,沒有解釋原因。
我自己思考了一下(午),也算是給出個解釋。
觀察題目,從樹的角度考慮,將切割過程看成一棵樹,根是原始木板,一刀下去以後得出兩個小木板就是它的兩個子節點,再切子節點……
最後的葉節點就是最終所要求的木板(L1...Ln
)。
將各節點所代表的木板的長度作為節點的權。
題目所求的開銷就是非葉子節點的權值之和。
觀察非葉子節點的組成,會發現其實每一個葉子節點在其每一個祖先節點上佔有其權值。
也就是說,權值之和等於
sum( weight(Li) * depth(Li) ) (1 <= i <= n)
最短的板與次短的板的節點應當是兄弟節點
為什麼?
其中depth(Li)
是Li所在深度,以depth(root)
為0。
如果我們將depth(Li)
看成編碼長度,而weight(Li)
看成字母權重,就可以理解這裡為什麼要用Huffman樹了。
那麼新的問題是,我忘了Huffman樹的證明了,不過現在時間緊急,留待以後去查吧。
Page 57 : 最長公共子序列問題的註腳①
如果稍微思考一下就能發現
s[i + 1] = t[j + 1]
時,只需令dp[i + 1][j + 1] = dp[i][j] + 1
就可以了。
我思考了一下(午)。
用反證法,設:
dp[i + 1][j] - dp[i][j] >= 2
根據轉移方程(Page 57頂),我們可以替換dp[i + 1][j]
,有:
dp[i][j - 1] - dp[i][j] >= 1 (與定義不符)
或
dp[i][j] - dp[i][j] >= 2 (與定義不符)
或
dp[i + 1][j - 1] - dp[i][j] >= 2
對於這種情況,我不知道如何直接表示其不行,不過可以繼續拆解它,有:
dp[i][j - 2] - dp[i][j] >= 1 (與定義不符)
或
dp[i][j - 1] - dp[i][j] >= 2 (與定義不符)
或
dp[i + 1][j - 2] - dp[i][j] >= 2
可以歸納,這樣一直持續下去,可得
dp[i + 1][0] - dp[i][j] >= 2 (與定義不符)
即必有
dp[i + 1][j] - dp[i][j] < 2
同理,有
dp[i][j + 1] - dp[i][j] < 2
Page 68 : 多重集合數
這個題,因為公式比較複雜(對我來說),我的感覺是看公式不如看程式碼清晰。
其實題目的思想比較簡單,首先可以簡單理解O(nm^2)
的演算法,然後觀察遞推關係,發現計算dp[i + 1]
中的每個值得計算都是用dp[i]
的一個固定長度的視窗的累和,所以用滑動視窗思想降低複雜度。剩下比較麻煩的是一些邊界條件處理。
Page 88 : 食物鏈
這個題比較抽象,難到我了,不過經過不懈的努力,還是理解了。
對我來說,題目最大的思維難點是為何要用三個元素表示一隻動物。
這個想通了非常簡單,列舉。
題目中所遭遇的困難是在處理過程中沒有辦法給予任意元素一個確定的值。
設想在處理過程中,一般地,我們有若干個集合。
相同集合的元素之間都有關係,不同集合中的元素都沒有關係。
此時如果要對所有元素確定性賦值,元素只要滿足其所在集合的要求就行了,其他集合對這個元素沒有要求。
但在處理過程中會發生集合合併:合併有確定賦值的集合A,B,有A中元素a,原先B對a不做要求,但是現在要要求a取特定值,如果原先A對a的賦值不滿足,則現在要跟據a重算A中所有元素的賦值以適應B。這一過程很複雜。
所以需要不確定的賦值,也就是列舉所有可能性。再看剛才的情形,某種確定的B對A中的a有確定的要求,只要將對應的a賦值與此種B關聯就好了。
Page 113 : 線段上格點的個數
為何是最大公約數?(雖然給了個圖解釋,不過我還是沒有直接領悟。)
給定一條兩端點都在整數座標上的斜線,有其在x軸上的投影長度為a,在y軸上的投影長度為b,a與b必為整數。
題目所求,即是最大的c,使得
a = da * c
b = db * c
成立。da,db為整數。
這也就是求a,b的最大公約數啦。
Page 119 : 埃氏篩法
受到下一小節(區間篩法)的啟發,這裡有一些細節。
// 摘自書中Page 119
int primes[MAX_N];
bool is_prime[MAX_N + 1];
int sieve(int n) {
int p = 0;
for (int i = 0; i < n; i++) is_prime[i] = true;
is_prime[0] = is_prime[1] = false;
for (int i = 2; i <= n; i++) {
if (is_prime[i]) {
prime[p++] = i;
for (int j = 2 * i; j <= n; j += i)
is_prime[j] = false;
}
}
return p;
}
注意到對於某個i和任意k(k < i)。
合法範圍內的k * i
必然已經被篩過了。因為k本身是素數或k的某個素因子。
所以對於內層迴圈j完全可以由i * i
開始。
同時,可以發現,對於列舉倍數的目的,i的上限可以是sqrt(n)
。此時,(sqrt(n), n]
範圍內的素數已被篩出。(這一範圍內的合數必然有一個小於等於sqrt(n)
的質因子。
相關文章
- 筆記:《挑戰程式設計競賽(第2版)》(2)筆記程式設計
- 筆記:《挑戰程式設計競賽(第2版)》(3)筆記程式設計
- 挑戰程式設計競賽選讀-選擇排序程式設計排序
- 《挑戰程式設計競賽(第2版)》譯者訪談問題有獎徵集程式設計
- 雲原生程式設計挑戰賽火熱開賽,51 萬獎金等你來挑戰!程式設計
- 程式設計挑戰程式設計
- 【筆記】《JavaScript高階程式設計(第3版)》(1)筆記JavaScript程式設計
- 某大學程式設計競賽程式設計
- 第 10 屆 CCPC 中國大學生程式設計競賽濟南站 遊記程式設計
- ACM-ICPC世界冠軍教你如何備戰程式設計競賽ACM程式設計
- 記微軟OpenHack機器學習挑戰賽微軟機器學習
- 《JavaScript高階程式設計第3版》-學習筆記-1JavaScript程式設計筆記
- 「 C++挑戰賽 」下週開始,最特別的程式設計題目等你挑戰!C++程式設計
- 【週週有獎】雲原生程式設計挑戰賽“邊緣容器”賽道邀你來戰!程式設計
- 第15屆浙江省大學生程式設計競賽D題程式設計
- 《java程式設計思想》筆記1Java程式設計筆記
- Android程式設計權威指南(第2版)—第14章挑戰練習Android程式設計
- Android程式設計權威指南(第2版)—第15章挑戰練習Android程式設計
- Android程式設計權威指南(第2版)—第12章挑戰練習Android程式設計
- pythonchallenge 挑戰筆記Python筆記
- html/css/javascript 程式設計挑戰HTMLCSSJavaScript程式設計
- 程式設計師的最大挑戰程式設計師
- 官宣!第三屆雲原生程式設計挑戰賽正式啟動!程式設計
- [補題] 第 45 屆國際大學生程式設計競賽(ICPC)亞洲區域賽(上海)程式設計
- 程式設計競賽中讀檔案技能程式設計
- 《Java核心技術(卷1)》筆記:第8章 泛型程式設計Java筆記泛型程式設計
- 2013程式設計之美全國挑戰賽資格賽之傳話遊戲薦程式設計遊戲
- Java高階程式設計筆記 • 【第4章 網路程式設計】Java程式設計筆記
- oracle程式設計藝術筆記-1Oracle程式設計筆記
- 雲原生程式設計挑戰賽 Less is more - Serverless 創新應用賽火熱開啟中程式設計Server
- 100+隊伍逐鹿大獎,創新程式設計挑戰賽秋季賽圓滿落幕程式設計
- 給黑客們的程式設計挑戰黑客程式設計
- [題解][2021-2022年度國際大學生程式設計競賽第10屆陝西省程式設計競賽] Type The Strings程式設計
- 勝因沙龍 - 程式設計競賽(持續更新)程式設計
- 紹興市大學生程式設計競賽程式設計
- 2024端午鋁紫程式設計競賽程式設計
- 【AI競賽】TinyMind漢字書法識別挑戰賽開始報名啦!!AI
- 伯樂線上程式設計挑戰第 0 期 - 來電轉駁系統程式設計