CSDN编程竞赛报名地址:https://edu.csdn.net/contest/detail/16
第二次参加 CSDN 竞赛了,上次赛后提了好多意见,不知道官方有没有看
不过相比上次,这次比赛确实优化了不少
比如页面内复制粘贴不会被警告了,界面也没有那么简陋了(但还是希望能继续优化)
此外还有一些方面想要反馈一下:
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——数学知识
这次题目都比较简单,象征性的写一下题解吧
X国最近开始严管枪火。 像是“ak”,“m4a1”,“skr”。都是明令禁止的。 现在小Q查获了一批违禁物品其中部分是枪支。
小Q想知道自己需要按照私藏枪火来关押多少人。 (只有以上三种枪被视为违法)
AC 代码:
#include
#include
#include
#include
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;
}
鬼画符门,每年都会统计自己宗门鬼画符消耗的数量,往年一直是大师兄管理, 但是这次鬼艺接手了, 你能帮鬼艺写一个程序统计每年消耗数量最多的鬼画符吗?
AC 代码:
#include
#include
#include
#include
#include
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;
}
已知字符串str,str表示邮箱的不标准格式。 其中”.”会被记录成”dot”,”@”记录成”at”。 写一个程序将str转化成可用的邮箱格式。(可用格式中字符串中除了开头结尾所有”dot”,都会被转换,”at”只会被转化一次,开头结尾的不转化)
这题最麻烦,当时废了不少时间
AC 代码:
#include
#include
#include
#include
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;
}
给一个无序数组,求最长递增的区间长度。如:[5,2,3,8,1,9] 最长区间 2,3,8 长度为 3
这题勉强算是个滑动窗口吧
AC 代码:
#include
#include
#include
#include
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;
}