【個人筆記】C++ ZeroJudge 基礎題庫解題(純練習) - part 3 === a020:https://zerojudge.tw/ShowProblem?problemid=a020 難度:★☆☆☆☆ 流程控制。 ```cpp= #include <iostream> #include <string> using namespace std; int main() { // 映射表,索引0對應A(10),1對應B(11),依此類推 int mapping[26] = { 10, 11, 12, 13, 14, 15, 16, 17, 34, 18, 19, 20, 21, 22, 35, 23, 24, 25, 26, 27, 28, 29, 32, 30, 31, 33 }; string id; cin >> id; char letter = id[0]; // 轉字母為數字 int num = mapping[letter - 'A']; int a = num / 10; // 十位數 int b = num % 10; // 個位數 int sum = a + b * 9; for (int i = 1; i <= 9; i++) { int digit = id[i] - '0'; if (i <= 8) { sum += digit * (9 - i); } else { sum += digit; } } if (sum % 10 == 0) { cout << "real" << endl; } else { cout << "fake" << endl; } return 0; } ``` --- c531.:https://zerojudge.tw/ShowProblem?problemid=c531 難度:★★★☆☆ 字串流應用、基本排序法、基本資料結構 ```cpp= #include <iostream> #include <string> #include <vector> #include <sstream> #include <algorithm> using namespace std; int main() { string line; // 逐行讀取輸入 while (getline(cin, line)) { stringstream ss(line); string token; vector<int> numbers; // 將一行分割並轉換為整數 while (getline(ss, token, ',')) { numbers.push_back(stoi(token)); } // 提取偶數 vector<int> evens; for (int num : numbers) { if (num % 2 == 0) { evens.push_back(num); } } // 對偶數進行升序排序 sort(evens.begin(), evens.end()); // 使用迭代器追蹤排序後的偶數 auto it = evens.begin(); for (size_t i = 0; i < numbers.size(); ++i) { if (numbers[i] % 2 == 0) { cout << *it; ++it; } else { cout << numbers[i]; } // 在非最後一個數字後添加逗號 if (i < numbers.size() - 1) { cout << ","; } } cout << endl; } return 0; } ``` stoi():字串轉整數,string to int。 --- e446.:https://zerojudge.tw/ShowProblem?problemid=e446 難度:★☆☆☆☆ 排列組合、列舉 ```cpp= #include <iostream> #include <algorithm> #include <vector> using namespace std; int main(){ ios::sync_with_stdio(false), cin.tie(nullptr); int n; cin >> n; vector <int> nums; for (int i=1;i<=n;i++){ nums.push_back(i); } do{ for (int n : nums) cout << n << " "; cout << "\n"; } while(next_permutation(nums.begin(), nums.end())); return 0; } ``` 最後一個測資點不知道是什麼鬼測資,測很久才發現 IO 要優化,記得別用 endl,用 '\n' 取代。 至於 `ios::sync_with_stdio(false), cin.tie(nullptr);` 要不要加其實沒差,但如果加了可以少 0.3 秒左右。 --- d212.:https://zerojudge.tw/ShowProblem?problemid=d212 難度:★★☆☆☆ 費氏數列、dp 優化 最簡單的解法就是遞迴解,但遞迴所花費的時間過多,在遞歸的時候會產生額外的計算開銷,也不會記錄答案。 ```cpp= #include <iostream> using namespace std; int main() { int n; while(cin >> n) { if(n == 1) { cout << 1 << endl; continue; } long long a = 1, b = 2, c; for(int i = 3; i <= n; i++) { c = a + b; a = b; b = c; } cout << b << endl; } return 0; } ``` 此程式碼為 DP bottom-up(由下往上) 的方式: 主要先處理最小子問題:`dp[1] = 1, dp[2] = 2`(a = 1, b = 2),再用迴圈慢慢回推上去:`dp[i] = dp[i-1] + dp[i-2]`,所以 i 從 3 開始。 時間複雜度:$$O(n)$$空間複雜度:$$O(1)$$ 以下是使用 top-down(由上往下) 的處理方式: ```cpp= #include <iostream> #include <vector> using namespace std; vector<long long> dp(100, -1); long long ans(int n) { if (n == 1) return 1; if (n == 2) return 2; if (dp[n] != -1) return dp[n]; return dp[n] = ans(n - 1) + ans(n - 2); } int main() { int n; while (cin >> n) { cout << ans(n) << endl; } return 0; } ``` Top-Down 就跟 Bottom-Up 相反: 主要先拆解大問題,再用遞迴去求出小問題,最後透過 DP 儲存答案一步步求出最終解答。 另外 Top-Down 也強調記憶化(Memorization)的部分,因為遞迴會導致一些重複計算的部分而產生效能開銷,所以這時候 DP 的作用就發揮出來了。`return dp[n] = ans(n-1) + ans(n-2)` 的部分就是將答案記起來,就不用重複算了。 Top-Down 的時間複雜度:$$O(n)$$空間複雜度:$$O(n)$$