C++可利用一個字元變數(char
)讀取中間的「:
」,例如:
想像我們如何處理直式減法:個位數不夠減,向十位數借 1 ,原個位數即可加 10 後再去減。當題目情境換成計算時間差,借了 1 分鐘,請問秒即可加多少再去減?
以下舉一個簡化版的例子來說明。假設題目給了兩個時間,格式為MM SS,分別代表分鐘和秒,保證第二個時間必大於第一個時間,我們嘗試以相同格式輸出時間 1 到時間 2 的時間差。
範例輸入 1 | 範例輸出 1 |
---|---|
10 31 13 20 |
2分49秒 |
範例輸入 2 | 範例輸出 2 |
13 18 20 32 |
7分14秒 |
程式碼先找出秒的差,無論分是否經過借位處理,都可以繼續往下找出分的差。
都瞭解了嗎?要再多一個位數囉。
三位數相減的狀況,若十位數為 0 ,就無法借了,需要再往上向百位數借 1 。借完之後,除了原個位數加 10 後再去減,原十位數還要再加 9 。
同理,當題目情境擴充成時、分、秒,若無分可借,往上借了 1 小時,請問分鐘數要另外加上多少?
只要把所有時間化成最小單位(秒),就沒有借位的問題了。以秒相減完,再使用取商運算子/
和取餘數運算子%
,即可非常快速地求出時間差為幾分幾秒。
以下舉一個簡化版的例子來說明。假設題目給了兩個時間,格式為MM SS,分別代表分鐘和秒,保證第二個時間必大於第一個時間,我們嘗試計算出兩個時間相差幾秒。
範例輸入 1 | 範例輸出 1 |
---|---|
10 31 13 20 |
2分49秒 |
範例輸入 2 | 範例輸出 2 |
13 18 20 32 |
7分14秒 |
眼尖的人會發現, m 也可以寫成((m2-m1)*60 + (s2-s1))/60
,這取決於個人的程式撰寫風格。可以選擇多令幾個變數,以簡化算式,或是少令幾個變數,直接輸出結果。
第二個時間小於第一個時間,表示有跨日。若要計算時間差,需要借來 24 個小時,也就是 86400 秒,再去進行運算。延續上個引導問題的範例,我們用分、秒來舉例。
我們繼續以上面簡化版的例子來說明。
若使用借位法,先算完秒的差,接著只要往上借 60 分鐘(不用還),即可求得真正的時間差。
而若使用時間單位轉換,直接借 3600 秒,也就是一小時,即可一勞永逸:
另外還有一種省略判斷式的寫法,運用取餘數運算子,來因應兩種不同情況:
同理,當題目情境擴充成時、分、秒,若第二個時間比較小,需要往上借 1 天,也就是 24 小時或 86400 秒。
[法一] 時、分、秒使用獨立的 if-else 架構,例如:
[法二] 內建函式:
利用<iomanip>
中的setw()
,調整輸出欄位寬度和setfill()
填補文字,例如:
這兩個函式的使用規則是什麼呢?請參考一個常見英文教學網站:GeeksforGeeks的說明,如果單用setw(數字)
函式,程式會讓「空格+待輸出字元」的總字元數,等於括弧內數字
個。而若在setw(數字)
前面再補上setfill(字元)
,該字元
會取代預設的空格,根據指定的總字元數,填補在待輸出字元的前面。兩個函式之間、前面、後面,都要記得加上<<
喔!
A. 可使用C++標準函式庫<algorithm>
中的內建函式sort()
。在章節2-1
就有簡單的使用範例,課本p.106
A. 方法有兩個。
【法一】循序搜尋法 (兩種搜尋方向)
【法二】極值變數法
A. 承上一個提示,兩種方法判斷的方式不太一樣。
A. 除了數字 N ,還要有暫存變數和總和變數,代表每一個 N 值的等邊三角形數(等比數列中每一項),以及每一項等邊三角形數加總(等比級數)。
本題每次重算 4 的次方會很崩潰(後述),而暫存變數的好處是,每次多乘以一個 4 ,就可以再累加到總和變數。
int
, long long
或unsigned long long
?A. 首先大家可以翻開以前的參考書,回憶這些資料型態可以存放整數範圍。已知 只看正整數的話,unsigned long long
能存放的範圍是:,大約接近20位數。
然而,題目告訴我們,N 值可能為 1 到 120 的正整數,也就是說最大為 120,於是我們可以使用等比數列、等比級數公式得知:
我們直接取來估位數,,。
顯然,這是unsigned long long
也無法hold住的數字範圍。
那麼要使用字串,還是使用整數陣列呢?
前者會需要提取出每個字元,在ASCII code和int
之間進行轉換,直觀、容易估算範圍,但位數判斷需要非常精確。而後者不用進行型別轉換,相較方便,以下將以後者進行說明。
A. 建議大家不要使用VLA,根據最大位數開一個已知大小的整數陣列。可以奢侈一點,把暫存(第幾項的)變數、總和變數,都開成大小為 100 的整數陣列。
A. 例如 1024 有 4 個位數,那麼可以用一個大小為 4 的整數陣列,索引值為多少,就代表第幾位數字:
數字 | 4 | 2 | 0 | 1 |
---|---|---|---|---|
索引值 | 0 | 1 | 2 | 3 |
為什麼建議從個位數開始存呢?雖然閱讀比較不方便,但等等在使用for
迴圈進行大數運算時,才能像直式運算一樣,統一由索引值最小的個位數開始計算。
請回憶國小學的直式運算。由個位數開始,一位一位地計算,且計算下一位之前,都要考慮前面是否有進位。以下示範 到 的直式運算邏輯(看起來很廢,但步驟要化成程式碼就要想一下了):
以 為例:
如果陣列開得夠大,確定可以用for
迴圈跑完每一位的計算並存放於整數陣列,那麼digit
變數就非必要了,最後從索引值較高者檢查,從第一個非 0 整數開始輸出每一位數即可。
本題除了乘以 4 ,乘完還要加總喔!雖然運算不同,同樣都要從個位數起一個一個位數運算,並將進位數字納入考量。比起觀念理解難度,更考驗的是細心程度,試試看吧!