点我补题
观前提醒 我的代码有一个最基本的多测架构,具体架构可以参照板子博客记录 的 Template.cpp 章节。对于多测场景,在 main
函数里负责读入数据组数,并且在 solve
函数里负责每一个单测的解题,这是一种比较好的习惯。在下面的题解代码中,我只会给出每一个单测的 solve 函数。不再赘述。
A.网络竞赛平台与小鹿与正在检验你是否是真人请稍后 思路 可以开一个桶记录从 0 到 9 每一位在输入数字中出现了多少次。题目要求没有前导 0,则首位肯定要从 1~9 中最小的一个数字出。然后就是从 0 到 9 依次输出即可。
针对于我的验题代码:我采用了字符串读入并遍历字符串来快速检索每一位的值(而不是每次%10 记录完后/10),并且采用了 map 代替堆来进行遍历。
代码(验题程序) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 void solve () { string str; cin >> str; map<int , int > mp; int mn = 10 ; for (auto ch : str) { mp[ch - '0' ]++; if (ch != '0' ) mn = min (mn, ch - '0' ); } string ans; ans.push_back (mn + '0' ); mp[mn]--; for (auto &[k, v] : mp) while (v) v--, ans.push_back (k + '0' ); cout << ans << endl; }
代码(新手友好版本) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 void solve () { int num; cin >> num; int cnt[10 ] = {0 }; int mn = 10 ; while (num) { cnt[num % 10 ]++; if (num % 10 != 0 ) mn = min (mn, num % 10 ); num /= 10 ; } cout << mn; cnt[mn]--; for (int i = 0 ; i <= 9 ; i++) { while (cnt[i] > 0 ) cnt[i]--, cout << i; } cout << endl; }
B.ICPC 与小鹿的差旅费用规划 思路 签到。输入 $a,b$ ,输出 $2a+b$。
但是 ,很多人做题的时候,一个是不明白多测的具体含义(这个我给出的样例也有锅,我谢罪),上来直接开写。
另外一些人则是做题不看数据范围,或者是不知道给出数据范围是干什么用的 ,这就不好。
在 C++中,int 变量在记录的时候,其上限能记录到 32 位二进制均为 1 的数字,也就是十进制的大约$2\cdot10^9$。而题目中给出的数据范围在 $2\cdot10^{15}$,明显超出此范围。
所以,要用 long long
。
十年算竞一场空,不开 long long
见祖宗。
代码 1 2 3 4 5 6 7 using i64 = long long ;void solve () { i64 a, b; cin >> a >> b; cout << a * 2 + b << endl; }
C.CCPC 与饭后消食的小鹿 思路 本题为 Atcoder Beginner Contest 240 C 题原题 ,并且数据点也是直接采用的 Atcoder 公开的数据点。
思路 小鹿每次跳跃都会从上一次发展而来,所以我们可以维护两个数组,一个用来记录“上一次跳跃”所到达的点,一个根据“上一次跳跃”到达的点计算本次跳跃到达的新点,然后每次计算完成后,用本次跳跃到达的点的数据覆盖上一次跳跃到达的点。数据范围足够小,不会超时。
思考题:这道题正解是动态规划,怎么样优化才能将暴力代码优化成动态规划的样子?动态规划是什么?
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 void solve () { int last[10200 ]; int cur[10200 ]; int n, x; cin >> n >> x; last[0 ] = 1 ; while (n--) { int a, b; cin >> a >> b; for (int i = 0 ; i <= x; i++) { if (last[i]) { cur[i + a] = 1 ; cur[i + b] = 1 ; } } for (int i = 0 ; i <= x; i++) { last[i] = cur[i]; cur[i] = 0 ; } } if (last[x]) cout << "Yes" << endl; else cout << "No" << endl; }
D.百度之星与小鹿的铁牌 思路 这个需要在纸上自行模拟一下路线,也就是为什么ACM竞赛会提供草稿纸。有些数学题不动笔墨是想不到做题思路的。
模拟路线个数以后可以很轻易的发现,从 $1$ 到 $n$ 的路径个数符合斐波那契数列规律,问题转化为求前30项斐波那契数列。
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 int fib[40 ];void init () { fib[1 ] = 1 , fib[2 ] = 1 ; for (int i = 3 ; i < 40 ; i++) fib[i] = fib[i - 1 ] + fib[i - 2 ]; } void solve () { int n; cin >> n; cout << fib[n] << endl; }
E.蓝桥杯与鹿与小面包 思路 智慧题。题目要求删除若干组数以后恰好留下一个最大的数,我们逆过来考虑,有哪些数被删除以后可以留下。
当一个数左侧有 $n\cdot k$个数的时候,其右侧也一定有 $m \cdot k$ 个数 $(n,m > 0)$,因为题目保证经过删除数字操作以后恰好只剩下一个数。
所以只需要计算满足条件的数字的最大值即可。
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 void solve () { int n, k; cin >> n >> k; int num, ans = 0 ; for (int i = 1 ; i <= n; i++) { cin >> num; if ((i - 1 ) % k == 0 ) ans = max (ans, num); } cout << ans; }
F.睿抗与小鹿的贪心消消乐 思路 模拟。按部就班的写,注意判断特殊情况(比如三个格子相邻且都是万能颜色 .
)即可。
考验代码底力的题目。
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 using Point = pair<int , int >;#define x first #define y second void solve () { int n; cin >> n; vector<string> grid (n + 1 ) ; for (int i = 1 ; i <= n; i++) cin >> grid[i], grid[i] = '$' + grid[i]; int q; cin >> q; while (q--) { int op; cin >> op; if (op == 1 ) { vector<Point> vec (3 ) ; vector<int > xs, ys; for (int i = 0 ; i < 3 ; i++) { cin >> vec[i].x >> vec[i].y; xs.push_back (vec[i].x), ys.push_back (vec[i].y); } sort (xs.begin (), xs.end ()); sort (ys.begin (), ys.end ()); set<char > st; if (xs[0 ] == xs[1 ] && xs[1 ] == xs[2 ] && ys[1 ] - ys[0 ] == 1 && ys[2 ] - ys[1 ] == 1 ) { for (auto &pt : vec) if (grid[pt.x][pt.y] != '.' ) st.insert (grid[pt.x][pt.y]); cout << (st.size () <= 1 ? "YES" : "NO" ) << endl; } else if (ys[0 ] == ys[1 ] && ys[1 ] == ys[2 ] && xs[1 ] - xs[0 ] == 1 && xs[2 ] - xs[1 ] == 1 ) { for (auto &pt : vec) if (grid[pt.x][pt.y] != '.' ) st.insert (grid[pt.x][pt.y]); cout << (st.size () <= 1 ? "YES" : "NO" ) << endl; } else cout << "NO" << endl; } else if (op == 2 ) { Point pt; char val; cin >> pt.x >> pt.y >> val; grid[pt.x][pt.y] = val; } } }
G.天梯赛与小鹿与字符串维护 思路 另一道模拟题。也是按部就班的模拟就好了,需要一定字符串知识。
如果看不懂题解代码,请先学习完C++的string字符串部分再来补题。
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 void solve () { int n; cin >> n; string str; cin >> str; vector<int > val (26 ) ; for (int i = 0 ; i < 26 ; i++) cin >> val[i]; int q; cin >> q; while (q--) { int op; cin >> op; if (op == 1 ) { string s; cin >> s; str += s; } else if (op == 2 ) { int ans = 0 ; for (auto ch : str) ans += val[ch - 'a' ]; cout << ans << endl; } else if (op == 3 ) { int l, r; cin >> l >> r; assert (r <= str.size ()); str = str.substr (0 , l - 1 ) + str.substr (r); } } }
Fun Facts 1.本套题目的主人公是教练鹿老师的儿子,他现在也是一名信息竞赛选手。当然,我们事先在出题的时候没有告诉鹿老师,所以他在看到题面的时候乐了好一阵。
2.所有的比赛背景介绍由我撰写。包括梗图也是我找的,看着感觉是不是还不错。
3.一开始想要拿一道大模拟做最难的题,并且一开始想要放在 A 题的位置。但是我们担心大家都不会写,最后取消了,放了个比较简单的题在 A 的位置上。
4.A 题想要教会大家两件事:题目难度与顺序无关,题目背景与题目无关。
5.消消乐题目经过了一次数据削弱,但是削弱后的随机数据卡掉了我的验题程序。(削弱后随机数据随机出了 ...
数据,这组数据成功卡掉了半数验题人的答案)
6.榜单的颜色不仅是想要对应彩虹色,比如青绿色和青蓝色对应言和和洛天依的弹幕应援色。所有的颜色都有对应的 VOCALOID 应援色,当然是我自己搞的。看看有没有有心人能收集全。(?
7.想要看大家比赛结果的我过于热切,于是物理补考只写了 30 分钟就匆匆交卷跑路了(??)
8.感谢所有集训队成员为新生赛做出的努力!