本文為2023年6月GESP C++四級的上機題目的詳細題解!覺得寫的不錯或者有幫助可以點個贊啦!
(第一次講解視頻,有問題可以指出,不足之處也可以指出)
目錄
題目一講解視頻:
題目二講解視頻:
題目一: 幸運數
題目大意:
解題思路:
代碼(C++):
題目二:圖像壓縮
題目大意:
解題思路:
代碼(C++):
題目一講解視頻:
2023年6月GESP C++四級上機題一
題目二講解視頻:
2023年6月GESP C++四級上機題二
題目一: 幸運數
B3850 [GESP202306 四級] 幸運數 - 洛谷
題目大意:
題目首先定義了,一個數字的個位數為第一位,十位數為第二位...以此內推。
然后呢,對于一個數字num的奇數位置,提取出來,然后進行如下操作:
定義這個數字為x,易得0 <= x <= 9。現在將x * 7,然后現在不斷的進行以下的操作,直到x小于等于9:
求出此時x的數位和sum,然后把x賦值成sum。
經過上述操作后,把x放回原來的位置。
如果num的數位和是8的倍數,那么num是幸運數,輸出T,否則輸出F。
解題思路:
題目主要考察的是模擬,代碼實現能力。
根據題目意思,我們主要的操作對象是num的奇數位置,我們可以把num轉換成字符串,可以輸入的時候直接用字符串變量接收。
注意個位數是字符串的最后一位,我們從字符串的最后一位開始遍歷,然后每次讓i -= 2即可保證獲取的是“奇數位置”。
然后根據題目意思進行模擬,在while (x > 9)的循環里面不斷的求出當前x的數位和,賦值給x,最后得出的x,直接把原來的位置的字符變成新的x即可,注意數字和字符之間的轉換。
最后不要忘記求出數位和,然后再判斷是否是8的倍數。
注意題目輸入的是N個數字,我們對每一個數字單獨判斷。
沒什么用的小優化:每個“奇數位置”的操作都是單獨進行的,那么肯定有一個對應值,我們可以先把每個數字操作的結果求出來放在數組里面,然后直接使用即可。
代碼(C++):
#include <bits/stdc++.h>
//https://blog.csdn.net/2401_83669813 csdn: @立志成為算法講師void solve() {//2.std::string s;std::cin >> s;int n = s.size();//3.for (int i = n - 1; i >= 0; i -= 2) {int num = s[i] - '0';num *= 7;//4.5.while (num > 9) {int t = num;int sum = 0;while (t > 0) {sum += t % 10;t /= 10;}num = sum;}//6.s[i] = num + '0';}int sum = 0;for (char c : s) {sum += c - '0';}if (sum % 8 == 0) {std::cout << "T\n";} else {std::cout << "F\n";}
}int main() {/*1.捆綁測試2.把數字當成字符串輸入3.從最后一位開始遍歷4.變換操作5.當數字大于9的時候,不斷的求數位和,然后賦值給新的數字6.把變換后的數字賦值回去*/int N;std::cin >> N;while (N--) {solve();}
}
題目二:圖像壓縮
B3851 [GESP202306 四級] 圖像壓縮 - 洛谷
題目大意:
給你n個長度為偶數,并且都相等的字符串s,這n個字符串組成一幅256級灰階的灰度圖像。
對于其中的一個字符串,每兩個字符組成一個字符串,表示一個16進制的數字,大小為0到255,也就是16進制的0到FF,這個大小表示這個像素點的灰階。題目保證n個字符串包含的灰階至少有16種。
現在我們要把這個256級灰階的灰度圖像壓縮成16級的灰度圖像。
壓縮方式為:
統計出這個圖像每一個灰階的數量,然后取數量最大的16種,如果存在灰階數量相同的灰階,那么灰階值小的在前面。
先把這16種灰階按照從大到小的順序輸出出來。
現在把這數量最大的16種灰階編號為0到F,也就是十進制的0到15。
對于其他的灰階y,我們計算出灰度與16個灰階最近的值(灰階大小,不是個數),也就是絕對值大小,把y編號成相差的絕對值最小的那個,如果有絕對值相同的點,那么我們就編號成編號小的那個。
然后把壓縮后的圖像輸出出來。
解題思路:
本題主要考察,進制的轉換,位運算,自定義排序,模擬,代碼實現能力。
我們首先把握題目的關鍵要求,把每兩個字符組成的字符串作為一個16進制數字,計算出出現次數最多的16個16進制數字,并且后面的排序和作差都要關注這16個16進制數字的大小。
那么我們可以這么寫,先把16進制轉換成10進制,然后我們用一個長度為256的數組cnt來記錄每一個16進制數字出現的次數。也就是cnt[i]為大小為i的數字的出現次數。
統計了出現次數后,我們現在進行自定義排序,求出里面最大的那16個數字。
由于題目要求:然后取數量最大的16種,如果存在灰階數量相同的灰階,那么灰階值小的在前面。
那我們可以這么簡單的寫,我們直接用一個數組id,來存0到255這些數字,然后排序這個數組,數組里面兩個數字的cnt[a] != cnt[b]的時候,cnt大的在前面,否則就是數字小的在前面。
這樣操作之后數組id里面的前16個數字就是我們想要的16個數字了。
可以先輸出出來,記得按照題目轉換回原來的16進制。
最后我們要實現的是,輸出壓縮后的圖像,對于每一個16進制的數字,先轉換成10進制,然后根據題目要求求出差的絕對值最小的那個,再根據題目要求編號成0 - F即可。
具體實現詳見代碼。
代碼(C++):
#include <bits/stdc++.h>
//https://blog.csdn.net/2401_83669813 csdn: @立志成為算法講師int toNum(char c) {if (c <= '9') {return c - '0';}return c - 'A' + 10;
}//16進制轉換成10進制
int to10(std::string s) {int res = toNum(s[0]) * 16 + toNum(s[1]);return res;
}char toChar(int num) {if (num < 10) {return num + '0';}return num - 10 + 'A';
}//10進制轉換成16進制
std::string to16(int num) {std::string res(2, '0');res[1] = toChar(num % 16);num /= 16;res[0] = toChar(num % 16);return res;
}int main() {/*1.用一個長度為256的數組cnt來統計出現次數2.把每一個256的數字都寫出來,用自定義排序根據cnt[i]和數字大小進行排序3.把最大的16個輸出出來4.把其他的數字進行壓縮*/int n;std::cin >> n;std::vector<std::string> a(n);for (int i = 0; i < n; i++) {std::cin >> a[i];}int m = a[0].size();//1.std::vector<int> cnt(256);for (auto& s : a) {for (int i = 0; i < m; i += 2) {std::string t = s.substr(i, 2); //從當前字符開始提取兩個字符int num10 = to10(t);cnt[num10]++;}}//cnt[i]就表示數字i出現的次數std::vector<int> mx16(256);for (int i = 0; i < 256; i++) {mx16[i] = i;}//2.std::sort(mx16.begin(), mx16.end(), [&](int u, int v){if (cnt[u] != cnt[v]) {return cnt[u] > cnt[v];}return u < v;});//3.for (int i = 0; i < 16; i++) {std::cout << to16(mx16[i]);}std::cout << "\n";//4.for (auto& s : a) {for (int i = 0; i < m; i += 2) {std::string t = s.substr(i, 2);int num = to10(t);int id, mnD = 256;for (int i = 0; i < 16; i++) {int d = abs(num - mx16[i]);if (d < mnD) {mnD = d;id = i;}}std::cout << toChar(id);}std::cout << "\n";}
}