# 🔔CPE必考49題 ## 🦤 1. Vito's Family * **題目** : ![image](https://hackmd.io/_uploads/HyfExa7GR.png) * **題目翻譯** * **題目描述 :** 世界知名黑幫 Vito Deadstone 即將搬到紐約。他在那裡有一個非常龐大的家庭,他們都住在拉馬菲亞大道上。由於他將經常拜訪所有的親戚,他正在尋找一個靠近他們的房子。Vito 想要將到所有親戚的總距離最小化,並且已經勒索了你來撰寫一個解決他問題的程式。 * **輸入 :** 輸入包含多個測試案例。第一行包含測試案例的數量。對於每個測試案例,你將會得到一個整數表示親戚的數量 r (0 < r < 500) 以及他們住的街道號碼 (也是整數) s1, s2, . . . , si, . . . , sr (0 < si < 30000)。請注意,有些親戚可能住在相同的街道號碼上。 * **輸出 :** 對於每個測試案例,你的程式必須輸出從最佳 Vito 的房子到每一個親戚的最小距離總和。兩個街道號碼 si 和 sj 之間的距離為 dij = |si − sj|。 * **程式碼** ```cpp= #include<iostream> #include<algorithm> using namespace std; int main() { // 關閉同步,提高輸入輸出效率 ios_base::sync_with_stdio(0); // 解除 cin 和 cout 的綁定,進一步提高效率 cin.tie(0); int n, m; cin >> n; // 讀取測試案例的數量 while (n--) { // 遍歷每個測試案例 cin >> m; // 讀取親戚的數量 int arr[m]; // 宣告一個長度為 m 的整數陣列,存放親戚的街道號碼 for (int i = 0; i < m; i++) { cin >> arr[i]; // 讀取每個親戚的街道號碼 } sort(arr, arr + m); // 將親戚的街道號碼按照升序排列 // 找出中位數,這樣可以使得到每個親戚的距離總和最小 int mid = arr[m / 2]; int sum = 0; // 初始化距離總和 // 遍歷每個親戚的街道號碼,計算到中位數的距離並加總 for (int i = 0; i < m; i++) { sum += abs(arr[i] - mid); } // 輸出距離總和 cout << sum << endl; } return 0; } ``` ## 🦤 2. Hashmat the brave warrior * **題目**: ![image](https://hackmd.io/_uploads/rkk4tFNMA.png) * **題目翻譯** * **題目描述 :** Hashmat是一名勇敢的戰士,他與一群年輕的士兵一起,從一個地方移動到另一個地方,與對手作戰。在戰鬥之前,他只計算一件事,即他的士兵數量與對手的士兵數量之間的差異。根據這個差異,他決定是否要進行戰鬥。Hashmat的士兵數量永遠不會超過對手的士兵數量。 * **輸入 :** 輸入包含每行的兩個數字。每行中的這兩個數字表示Hashmat軍隊和他的對手軍隊的士兵數量,或者相反。輸入的數字不大於2^32。輸入以“End of File”終止。 * **輸出 :** 對於每一行輸入,請打印出Hashmat軍隊和他的對手軍隊之間士兵數量的差異。每個輸出應該在單獨的一行中。 * **程式碼** ```cpp= #include <iostream> using namespace std; int main() { // 宣告變數a和b,用於儲存Hashmat軍隊和對手軍隊的士兵數量 long long a, b; // 循環讀取輸入直到檔案結束 while (cin >> a >> b) { // 輸出Hashmat軍隊和對手軍隊士兵數量之間的差值的絕對值 cout << abs(b - a) << endl; } return 0; } ``` ## 🦤 3. Primary Arithmetic * **題目** : ![image](https://hackmd.io/_uploads/S1hlzoNz0.png) * **題目翻譯** * **題目描述 :** 兒童被教導從右至左逐位數將多位數相加。許多人發現“進位”操作 - 將一個1從一個數位位置進位到下一個以相加 - 是一個重大挑戰。你的任務是計算一組加法問題中的進位操作次數,以便教育工作者可以評估它們的難度。 * **輸入 :** 每行輸入包含兩個小於10位數的無符號整數。輸入的最後一行包含“0 0”。 * **輸出 :** 對於每行輸入,除了最後一行,您應該計算並打印出從將兩個數字相加所產生的進位操作的數量,格式如下所示: * **程式碼** ```cpp= #include<iostream> using namespace std; int main() { int carry = 0; // 初始化進位 int ans = 0; // 初始化進位操作次數 int n, m; // 宣告變數n和m,用於存儲輸入的數字 while (true) { // 進入無限循環,直到遇到條件跳出 cin >> n >> m; // 讀取輸入的兩個數字 if (n == 0 && m == 0) // 如果兩個數字均為0,跳出循環 break; carry = 0; // 初始化進位為0 ans = 0; // 初始化進位操作次數為0 while (n != 0 || m != 0) { // 進入兩數相加的迴圈 if (n % 10 + m % 10 + carry > 9) { // 如果兩個數字的個位相加加上進位大於9 carry = 1; // 設置進位為1 ans = ans + 1; // 進位操作次數加1 } else { // 否則 carry = 0; // 重置進位為0 } n = n / 10; // 將n除以10取整,即刪除個位 m = m / 10; // 將m除以10取整,即刪除個位 } // 根據進位操作次數輸出結果 if (ans == 0) cout << "No carry operation." << endl; if (ans == 1) cout << "1 carry operation." << endl; if (ans > 1) cout << ans << " carry operations." << endl; } return 0; } ``` ## 🦤 4. 3n+1 problem * **題目** : ![image](https://hackmd.io/_uploads/ByXMQaSf0.png) ![image](https://hackmd.io/_uploads/rJ1QQ6rzC.png) * **題目翻譯** * **題目描述 :** ![image](https://hackmd.io/_uploads/Sy1DHTSzR.png) ![image](https://hackmd.io/_uploads/S1A5SpBfA.png) * * **輸入 :** 輸入將包含一系列整數對 i 和 j,每行一對整數。所有整數都將小於10,000且大於0。 你應該處理所有整數對,對於每對整數,確定在 i 和 j 之間(包括 i 和 j)的所有整數中的最大循環長度。 你可以假設沒有操作會導致32位整數溢出。 * **輸出 :** 對於每對輸入整數 i 和 j,你應該輸出 i、j 和在 i 和 j 之間(包括 i 和 j)的所有整數的最大循環長度。這三個數字應該至少用一個空格分隔,並且所有三個數字都在一行上,對於每行輸入,輸出一行。整數 i 和 j 必須按照它們在輸入中出現的順序出現在輸出中,並且應該在最大循環長度之後(在同一行上)。 * **程式碼** ```cpp= #include<iostream> using namespace std; // 定義函數 f,計算循環長度 int f(int k) { int ans = 1; while (k != 1) { if (k % 2 == 0) { k = k / 2; } else { k = k * 3 + 1; } ans++; } return ans; } int main() { int i, j; while (cin >> i >> j) { cout << i << " " << j << " "; int max = 0; // 初始化最大循環長度為0 // 確保i小於j,如果不是,交換它們的值 if (j < i) { int temp = j; j = i; i = temp; } // 遍歷所有從i到j的數字,計算最大循環長度 for (int min = i; min <= j; min++) { if (f(min) > max) max = f(min); } cout << max << endl; // 輸出i、j和最大循環長度 } return 0; } ``` * **題目** : ## 🦤 5. You can say 11 ![image](https://hackmd.io/_uploads/S1h4haHGR.png) * **題目翻譯** * **題目描述 :** 你的任務是,給定一個正數N,判斷它是否是11的倍數。 * **輸入 :** 輸入是一個文件,每行包含一個正數。 包含數字「0」的行是 輸入結束。 給定的數字最多可以包含 1000 位數字。 * **輸出 :** 程式的輸出應指示每個輸入數字是否為 11 的倍數 * **程式碼** ```cpp= #include<iostream> using namespace std; int main() { string n; int n1, n2; while (cin >> n) { n1 = 0; n2 = 0; if ((n == "0") && (n.length() == 1)) { // 當輸入為0時跳出迴圈 break; } for (int i = 0; i < n.length(); i++) { // 遍歷輸入數字的每一位 if ((i + 1) % 2 == 0) { // 如果是偶數位 n1 += n[i] - '0'; // 將該位數字加入n1中 } else { // 如果是奇數位 n2 += n[i] - '0'; // 將該位數字加入n2中 } } if (abs(n2 - n1) % 11 == 0) // 如果n2和n1的差值能被11整除,則輸出是11的倍數 cout << n << " is a multiple of 11." << endl; else // 否則輸出不是11的倍數 cout << n << " is not a multiple of 11." << endl; } return 0; } ``` ## 🦤 5. * **題目翻譯** * **題目描述 :** * **輸入 :** * **輸出 :** * **程式碼** ```cpp= ```