1048 數字加密 (20 point(s))
// 錯誤魔改後正確版 #include <bits/stdc++.h> using namespace std; int main() { // 加密整數A 加密序列B string A, B, str = "0123456789JQK" ; cin >> A >> B; // 高位補零 // 獲取A比B多出來的位數並轉換為下標 for( int i = A.size() - B.size() - 1; i >= 0; i--){ B.insert(0, 1, '0'); } int flag = 1; // 右向左為高位 個位第一位 for(int i = A.size() - 1, j = B.size() - 1; i >= 0 && j >= 0; i--, j--){ // 每位數字 與A對應位置運算 // A奇數位置 相加後 13取餘 J 10 Q 11 K 12 if(flag){ flag = 0; // 直接替換B位置元素 int tmp = (int)(A[i] + B[j] - 2 * '0') % 13; B[j] = str[tmp]; } // 偶數 B 減去A 結果為負再加 10 else{ flag = 1; int tmp = B[j] - A[i]; if(tmp < 0) tmp += 10; B[j] = tmp + '0'; } } cout << B; } }
原來少考慮了一種情況。原本的想法是照著樣例給出的一種條件,當 B 長於 A 的時候,高位 B 可以直接輸出。所以最開始寫的時候,僅僅只是考慮了 B > A 的時候。
並且最開始連 “與A對應位置運算” 這個條件也沒有正確理解。以為左邊才是對應的位置,從左邊向右邊一一對應。但結合另一個條件 “個位為第 1 位”,實際應該是從右邊到左邊為低位到高位,從右到左一一對應。
換句話來說就是左對齊和右對齊的區別,而這裡則是右對齊。
所以這兩個理解不正確,導致對 A < B 的時候沒能夠正確理解,同時因為沒有正確位置上高位補零,導致卡測試點2。
學別人補零之後反而卡了測試點零、四五。結果一個個排除居然是奇偶位置判斷的問題。
因為剛開始是照著題目要求判斷奇偶位置的,結果發現由於下標會 - 1,導致用下標判斷的話會導致奇偶結果互換。所以就從 i % 2 == 1 改成 i % 2 == 0 為奇數。
但這反而會導致測試點4和5的錯誤。最後學別人用flag記錄,輸出一個換一個處理方法,才能全部AC。
但還是不太理解,為什麼會有這樣的錯誤,難道奇偶不是隔一個出現?為什麼會出現這樣寫判斷會有問題?
不過看別人的程式碼,如果從屁股開始遍歷的話,也可以用用 reverse() 函式將字串倒置,而可以從 i = 0 開始遍歷。
而這樣寫,就可以用 i & 2 來判斷奇偶。真是神祕。
參考別人還學到兩個東西,一個是關於字元陣列比如
char str[13] = { '0','1','2','3','4','5','6','7','8','9','J','Q','K' };
可以寫成
string str = "0123456789JQK";
這樣就不需要寫這麼多 '' 了,使用上也是一致的。
還有就是字串的拼接,原本以為是Java的,原來C++也可以實現這麼方便的操作。比如別人高位補零的是這樣寫的。
while (A.size() < B.size()) { A = '0' + A; }
while (A.size() > B.size()) { B = '0' + B; }
寫的時候注意的,關於數字字元的運算後轉換成數字的問題。
如果是兩個數字字元相加的時候,需要減去兩個 '0',才能轉換成真正的數字。
而相減的時候,因為數字字元本身帶有 '0' ,所以相減的時候直接就減去了,直接就轉換成真正的數字,不需要額外加減 '0'。