CSDN竞赛—第六期题解与感想
CSDN編程競賽報名地址:https://edu.csdn.net/contest/detail/16
CSDN競賽—第六期題解與感想
- 前言/背景
- 參賽經歷
- 解題思路
- 經驗心得
- 資料分享
- 第六期題解
- 1. 嚴查槍火
- 2. 鬼畫符門
- 3. 收件郵箱
- 4. 最長遞增的區間長度
前言/背景
第二次參加 CSDN 競賽了,上次賽后提了好多意見,不知道官方有沒有看
不過相比上次,這次比賽確實優化了不少
比如頁面內復制粘貼不會被警告了,界面也沒有那么簡陋了(但還是希望能繼續優化)
此外還有一些方面想要反饋一下:
- 能否考慮 C++ 代碼模板加上 using namespace std;
- 希望題目難度方面再多斟酌下,有難有易有區分比較好
- 能否考慮統一競賽開始時間,而不是用戶自己選擇時間進入考試,可以減少二次參賽的作弊情況
這次題目真的很簡單了,賽后看自己的排名是 28 名
因為很多人都是滿分,所以同分數按時長排名
但最后獲獎通知里發現自己居然是第 10 名,原來前面的那么多人都被判違規取消成績了,啊這……
參賽經歷
我個人此前的參賽經歷只有力扣周賽和藍橋杯而已
力扣競賽積分在 2000 分出頭,藍橋杯成績是 C/C++ B組 國二
能力馬馬虎虎,水平時高時低,這兩次 CSDN 競賽勉強打到十名左右
上次(第五期)是第九名,這次第十名
解題思路
讀題
要讀清楚題目的邏輯和設定,要求的什么問題,輸入輸出的格式,以及數據規模有多大
看套路
看是否用到了哪些套路
比如上次第五期最后一題就是二分的模板題,有了解的話很快就能寫出來
如果能看出用到了什么套路,解題會容易許多
預估復雜度
一般認為,復雜度在 108 以內是可以通過的
那么有時可以根據數據規模的大小,來猜測要用到那種算法
而且很少有題目會卡在極限的規模
如果 n <= 109,可以估計復雜度為 O(logn),考慮二分
如果 n <= 105 或者 n <= 106,這兩個是比較常見的規模,這種規模可能猜不出什么東西,因為它可以排序 O(n * logn),前綴和 O(n),動規, 記憶化搜索,并查集,等等……
如果 n <= 103,可以估計復雜度為 O(n^2),可能是二維的動態規劃,或者記憶化搜索
如果 n <= 100,這個規模就很寬松了,因為理論最大可以是 O(n^4) 的復雜度,但很少會出現這樣的復雜度,這時可以嘗試無腦深搜
如果 n <= 25,可以估計復雜度為 O(2^n),在這個復雜度的可以考慮狀壓dp
如果 n <= 10,可以估計復雜度為 O(n!),n 的階層復雜度的,肯定是有循環的深搜了
自測樣例
自己寫幾個樣例測一下,但要有針對性地寫,寫一些特殊地值,或者臨界值
但是 CSDN 是可以隨意提交地,可以先提交測測,再自己寫樣例找 bug
調試bug
在關鍵點輸出一些信息,看看是否正常運行,這是最基本的操作了
如果遇到某些運行錯誤,但無法定位錯在哪里
可以試試注釋掉一半代碼看能否運行,不斷縮小注釋的范圍來定位 bug 所在的點
經驗心得
算法的思路,其實大多還是套路
如果自己沒有接觸過題中的套路,就只能拼自己的靈活思考了
但是,套路中其實藏著各種各樣的思維方式
所以,提升算法能力的最好方法就是多刷題
一來了解更多套路,之后遇見類似的題,心里已經知道怎么做了
二來開闊思維,靈活應對各類變種題
下面是一些競賽常用的套路或思維,做題沒有頭緒時,可以一 一試想這些方法是否可行:
- 二分,排序,滑動窗口,前綴和,深搜,廣搜,最短路,記憶化搜索,并查集,逆向思維,貪心,動態規劃,線段樹,數學
算法的盡頭是數學,如果有些題不能直接用一些算法套路來應對,那這極有可能是一道數學題
像上次的第五期競賽,前兩題都考察了質因數相關的點,第三題用逆向思維去考慮,可以用到深搜,也可以動態規劃,第四題則是二分
但這期競賽題目過于簡單了,貌似沒有用到算法相關的東西,都是一些語法層面的業務問題,大概也就課后作業的水準,我甚至已經忘記題目都是什么了……
資料分享
分享一下 y總 寫的常用代碼模板:
常用代碼模板1——基礎算法
常用代碼模板2——數據結構
常用代碼模板3——搜索與圖論
常用代碼模板4——數學知識
第六期題解
這次題目都比較簡單,象征性的寫一下題解吧
1. 嚴查槍火
X國最近開始嚴管槍火。 像是“ak”,“m4a1”,“skr”。都是明令禁止的。 現在小Q查獲了一批違禁物品其中部分是槍支。
小Q想知道自己需要按照私藏槍火來關押多少人。 (只有以上三種槍被視為違法)
AC 代碼:
#include <iostream> #include <string> #include <sstream> #include <vector>using namespace std;int solution(int n, std::vector<std::vector<std::string>> &vec) {int res;for (auto &a : vec) {for (auto &s : a) {if (s == "ak" || s == "m4a1" || s == "skr") {res++;break;}}}return res; }int main() {int n;std::vector<std::vector<std::string>> vec;std::cin >> n;std::string line, token;for (size_t i = 0; i < n; i++) {std::vector<std::string> s;getline(std::cin >> std::ws, line);std::stringstream tokens(line);while (std::getline(tokens, token, ' ')) {s.push_back((token));}vec.push_back(s);}int result = solution(n, vec);std::cout << result << std::endl;return 0; }2. 鬼畫符門
鬼畫符門,每年都會統計自己宗門鬼畫符消耗的數量,往年一直是大師兄管理, 但是這次鬼藝接手了, 你能幫鬼藝寫一個程序統計每年消耗數量最多的鬼畫符嗎?
AC 代碼:
#include <iostream> #include <string> #include <sstream> #include <vector> #include<map>using namespace std;std::string solution(int n, std::vector<std::vector<std::string>> &vec) {string res;int mx = -1;map<string, int> mp;for (auto &a : vec) {for (auto &s : a) {mp[s]++;}}for (auto &[k, v] : mp) {if (mx < v) {mx = v;res = k;}}return res; }int main() {int n;std::vector<std::vector<std::string>> vec;std::cin >> n;std::string line, token;for (size_t i = 0; i < n; i++) {std::vector<std::string> s;getline(std::cin >> std::ws, line);std::stringstream tokens(line);while (std::getline(tokens, token, ' ')) {s.push_back((token));}vec.push_back(s);}std::string result = solution(n, vec);std::cout << result << std::endl;return 0; }3. 收件郵箱
已知字符串str,str表示郵箱的不標準格式。 其中”.”會被記錄成”dot”,”@”記錄成”at”。 寫一個程序將str轉化成可用的郵箱格式。(可用格式中字符串中除了開頭結尾所有”dot”,都會被轉換,”at”只會被轉化一次,開頭結尾的不轉化)
這題最麻煩,當時廢了不少時間
AC 代碼:
#include <iostream> #include <string> #include <sstream> #include <vector>using namespace std;bool check_at(string &s, int i) {return s.length() > i + 2 && s[i] == 'a' && s[i + 1] == 't'; }bool check_dot(string &s, int i) {return s.length() > i + 3 && s[i] == 'd' && s[i + 1] == 'o' && s[i + 2] == 't'; }std::string solution(std::string str) {string res = "";res += str[0];bool f = false;for (int i = 1; i < str.size(); i++) {if (check_at(str, i) && !f) {f = true;res += "@";i += 1;} else if (check_dot(str, i)) {res += ".";i += 2;} else res += str[i];}return res; }int main() {std::string str;std::cin >> str;std::string result = solution(str);std::cout << result << std::endl;return 0; }4. 最長遞增的區間長度
給一個無序數組,求最長遞增的區間長度。如:[5,2,3,8,1,9] 最長區間 2,3,8 長度為 3
這題勉強算是個滑動窗口吧
AC 代碼:
#include <iostream> #include <string> #include <sstream> #include <vector>int solution(int n, std::vector<int> &a) {int ans = 1;int len = 1;for (int i = 1; i < n; i++) {if (a[i] > a[i - 1]) len++;else len = 1;ans = std::max(ans, len);}return ans; }int main() {int n;std::vector<int> vec;std::cin >> n;std::string line_0, token_0;getline(std::cin >> std::ws, line_0);std::stringstream tokens_0(line_0);while (std::getline(tokens_0, token_0, ' ')) {vec.push_back(std::stoi(token_0));}int result = solution(n, vec);std::cout << result << std::endl;return 0; }總結
以上是生活随笔為你收集整理的CSDN竞赛—第六期题解与感想的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: visual assistant x 破
- 下一篇: (区块链溯源)基于Hyperledger