L1-1 哪吒的宣言
C 语言
#include <stdio.h>int main(void) {printf("If the world won't accept me, I'll twist it to my will!");return 0;
}
Python
print("If the world won't accept me, I'll twist it to my will!")
L1-2 哪吒求和
#include<stdio.h>
int a[12];
int main()
{int sum=0;for(int i=1;i<=10;i++){scanf("%d",&a[i]);sum+=a[i];}printf("%d",sum);return 0;}
L1-3 找到HarryPotter
读入一个字符串然后遍历一遍即可,找到字符串中为h的字符,然后将它替换
#include<iostream>using namespace std;signed main() {string s;cin >> s;for (int i = 0; i < s.size(); i++) {if (s[i] == 'h') {s[i] = '#';}}cout << s << endl;return 0;
}
L1-4 Shinji Ikari
只需要判断每个下标是否是质数即可。该题数据量较小,可暴力判断。
注意1不是质数。
#include <bits/stdc++.h> #define pii pair<int,int>
#define piii pair<int, pair<int, int>>
#define int long long using namespace std; bool isprime(int x) { if (x == 1) return 0; if (x == 2 || x == 3) return 1; for (int i = 2; i <x; i++) { //此处可直接暴力到x-1if (x % i == 0) { return 0; } } return 1;
} void solve() { int n; cin >> n; for (int i = 1; i <= n; i++) { int x; cin >> x; if (!isprime(i)) cout << x << " "; }
} signed main() { int T = 1; while (T--) { solve(); } return 0;
}
L1-5 零件检测
通读题干后可以得出题目要求的是n次循环中每个零件的实际误差之和除以n,与p进行比较,如果该平均值不大于p,输出Yes,否则输出No,并保留6位小数输出实际误差。 代码如下:
#include<stdio.h>int main()
{int n ;double k , p ;scanf("%d%lf%lf",&n , &k , &p) ;double sum = 0 ;for(int i = 1 ; i <= n ; i ++) {double x ;scanf("%lf", &x) ;if(x - k >= 0) sum += x - k ;else sum += k - x ;}sum = (1.00 * sum) / (1.00 * n) ;if(sum <= p) printf("Yes\n") ;else printf("No %6lf\n" , sum) ;return 0 ;
}
L1-6 用电量预测误差
按题意来,无需多言。
C 语言
#include <stdio.h>
#include <stdlib.h>int main(void) {int P[24], A[24];for (int i = 0; i < 24; ++i) {scanf("%d", &P[i]);}for (int i = 0; i < 24; ++i) {scanf("%d", &A[i]);}int maxDiff = 0;for (int i = 0; i < 24; ++i) {int diff = abs(P[i] - A[i]);if (diff > maxDiff) {maxDiff = diff;}}printf("%d\n", maxDiff);return 0;
}
Python
P = map(int, input().split())
A = map(int, input().split())
print(max(abs(p - a) for p, a in zip(P, A)))
L1-7 跨文化交际
遍历字符串,如果在原字符串S中遇到字符C,输出P字符串即可。请注意吸收换行符,代码如下:
#include<stdio.h>
#include<string.h>const int N = 2e5 + 10 ;int main()
{char s[N] ;scanf("%s",s) ;getchar() ;char c ;scanf("%c" , &c) ;getchar() ;char p[N] ;scanf("%s" , p) ; for(int i = 0 ; i < strlen(s) ; i ++) {if(s[i] != c) {printf("%c" , s[i]) ;} else {printf("%c" , s[i]) ;for(int j = 0 ; j < strlen(p) ; j ++) {printf("%c" , p[j]) ;}}}return 0 ;
}
L1-8 马拉松站点补给
通过循环模拟分配过程:
初始化长度为num_people的全零数组
定义当前应分配数量current,从1开始递增
循环分配能量胶,每次取min(current,剩余数量)
利用取模运算实现循环索引
#include <vector>
#include <algorithm>
#include<iostream>
int res[10000] = {0};
void distributeSupplies(int supplies, int num_stations) {int current = 1; int index = 0;while (supplies > 0) {int allocation = std::min(current, supplies); res[index % num_stations] += allocation; supplies -= allocation; current++; index++;}
} int main() {int n, m; std::cin >> n >> m;distributeSupplies(n, m);for (int i = 0; i < m; i++){std::cout << res[i] << " ";} return 0;
}
复杂度分析
时间复杂度:O(√n),因每次分配量递增,循环次数约为√(2*n)
空间复杂度:O(m),仅需维护结果数组
该方法通过循环和取模运算高效实现了符合赛事规则的分配过程,确保正确处理边界情况
L2-1 炼化
排序问题,数据量比较小,可以直接使用冒泡排序进行排序。
#include<stdio.h>
int a[1005];
int n;
int main()
{scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d",&a[i]);}for(int i=1;i<n;i++){for(int j=1;j<=n-i;j++){if(a[j]>a[j+1]){int t=a[j];a[j]=a[j+1];a[j+1]=t;}}}for(int i=1;i<=n;i++){printf("%d",a[i]);if(i!=n)printf(" ");elseprintf("\n");}printf("%d",a[n]);return 0;}
L2-2 勇闯玉虚宫
本题有两个坑点:
- 一个就是k的值可能过大,导致越界,所以在暴力遍历数组下标的时候要判断一下会不会越界
- 另外一个就是最后的和会爆 int 所以要开long long
#include<bits/stdc++.h>using namespace std;#define int long longsigned main() {int n;cin >> n;vector<vector<int>> a(n + 1, vector<int> (n + 1));for (int i = 1; i <= n; i++) {for (int j = 1; j <= n; j++) {cin >> a[i][j];}}int x, y, k;cin >> x >> y >> k;int sum = 0;for (int i = x - k / 2; i <= x + k / 2; i++) {for (int j = y - k / 2; j <= y + k / 2; j++) {if (i <= 0 || i > n || j > n || j <= 0) continue;sum += a[i][j];}}cout << sum << endl;return 0;
}
L2-3 MyGO!!!!!
首先我们需要搞懂两个下标,一个是有效音符的下标,一个是给定的音符串的下标。搞懂这个,做法就很清晰了。其次,此题目判断质数的时候,不能再暴力到x-1,必须到根号x的位置。
#include <bits/stdc++.h> using namespace std; bool isprime(int x) { if (x == 1) return 0; for (int i = 2; i * i <= x; i++) { if (x % i == 0) { return 0; } } return 1;
} int main() { int n, k; int atleast; cin >> n >> k >> atleast; int idx = 1; //总音符串中的下标int tr = 1; //实际有效音符下标vector<int> arr(n + 1); for (int i = 1; i <= n; i++) cin >> arr[i]; for (; idx <= n; idx++) { if (arr[idx] != (1 + (tr - 1) * k) * (1 + (tr - 1) * k)) { if (!isprime(arr[idx])) { cout << "Wrong!" << endl; cout << idx << endl; return 0; } } else { tr++; } } if (tr >= atleast) { cout << "It's MyGO!!!!!" << endl; } else { cout << "Useless!" << endl; } }
L2-4 空间优化
本题主要考察对于结构体构造,简单暴力查重能力的考查,在c++语言中class与c语言的struct高度类似,本题用class实现,先开一个class数组存放id和email的信息,然后从头开始遍历将所有email相等的id保留第一个即可
#include <vector>
#include <unordered_map>
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;struct Person {int id;string email;
};Person p[1000];int main() {int n;cin >> n;for (int i = 0; i < n; i++) {cin >> p[i].id;cin >> p[i].email;}for (int i = 0; i < n; i++) {if (p[i].email != "") {for (int j = i + 1; j < n; j++) {if (p[i].email == p[j].email) {p[j].email = "";}}}}for (int i = 0; i < n; i++) {if (p[i].email != "") {cout << p[i].id << " " << p[i].email << endl;}}return 0;
}
L3-1 服务器性能排行榜
在竞赛中,一般认为每秒可以执行 5×10⁸ 次运算。
本题 n 的数量级达到 10⁵。排序时必须使用时间复杂度为 O(log n) 的排序算法。
删除数据时,不可暴力遍历,需要使用高效的数据结构。用集合或映射能实现最快 O(1) 时间复杂度内删除元素。
C++
以下 main 函数的前两行代码可以加快读入数据速度,是竞赛常用技巧。
#include <algorithm>
#include <iostream>
#include <unordered_set>
#include <vector>
using namespace std;struct Server {int id;int responseTime;
};int main() {ios::sync_with_stdio(false);cin.tie(nullptr);int n;cin >> n;vector<Server> servers;for (int i = 0; i < n; i++) {int id, responseTime;cin >> id >> responseTime;servers.push_back({id, responseTime});}int m;cin >> m;unordered_set<int> toDelete;for (int i = 0; i < m; i++) {int id;cin >> id;toDelete.insert(id);}// 过滤掉需要删除的服务器vector<Server> remaining;for (const auto &s : servers) {if (toDelete.find(s.id) == toDelete.end()) {remaining.push_back(s);}}// 按照响应时间升序,若相同则按 ID 升序sort(remaining.begin(), remaining.end(),[](const Server &a, const Server &b) {return a.responseTime == b.responseTime? a.id < b.id: a.responseTime < b.responseTime;});// 输出排序后服务器 IDfor (const auto &s : remaining) {cout << s.id << "\n";}return 0;
}
Python
在 Python 中,多次调用 `input()` 函数速度较慢,因此一次读入所有数据并转换成数字。
import sysinput = map(int, sys.stdin.read().split())n = next(input)
servers = {}
for _ in range(n):id = next(input)time = next(input)servers[id] = time # 在 servers 中保存 id:time 映射m = next(input)
for _ in range(m):del_id = next(input) # 读入需要删除的 IDservers.pop(del_id, None) # 删除 del_id # 对于一对 id:time 优先以 time 排序,其次是 id
sorted_servers = sorted(servers.items(), key=lambda x: (x[1], x[0]))# 输出答案
sys.stdout.write("\n".join(str(id) for id, _ in sorted_servers))
L3-2 最小的数字
本题暴力遍历每个操作的话会超时,但是我们可以发现一个性质:
- 当改变的值包括最小值的时候,最小值-- / ++
- 当改变值不包括最小值的时候,最小值不变。
- 而又因为每次操作数字只会改变1,所以当第二大的数字被操作时,即使它--,也不会比最小的数字更小。
所以综上,我们只需要维护最小的数字看它是否增加或者减少
#include<bits/stdc++.h>using namespace std;signed main() {int n, m;cin >> n >> m;vector<int> a(n + 1);for (int i = 1; i <= n; i++) {cin >> a[i];}int Min = *min_element(a.begin() + 1, a.end());while(m--) {int op, l, r;cin >> op >> l >> r;if (Min >= l && Min <= r) Min += op;cout << Min << endl;}return 0;
}
L3-3 Just Monika
宽度优先搜索(BFS)。在bfs中,我们每次往四周走一层,在这样的前提下第一次到达某个点(x,y)距离一定是最近的。前提是每条路线的长度都一样。
我们用队列来存储每次延申的时候四个方向的点。由于要求字典序最小,故按照上下左右四个方向把待搜索的点加入队列。用vis来保证一个点只搜索一次,用prev来记录每个点的前驱位置,用prevDir来记录从哪个方向转到x y这个点。
#include <bits/stdc++.h> using namespace std;
#define int long long
#define pii pair<int,int> int dx[] = {-1, 1, 0, 0}; // 上、下、左、右
int dy[] = {0, 0, -1, 1};
int dir[] = {1, 2, 3, 4}; // 1=上, 2=下, 3=左, 4=右 void solve() { int n, m; cin >> n >> m; vector<vector<int>> arr(n, vector<int>(m)); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { cin >> arr[i][j]; //邻接表存点之间的关系。} } vector<vector<int>> dist(n, vector<int>(m, 1e9)); vector<vector<int>> vis(n, vector<int>(m, 0)); vector<vector<int>> prevDir(n, vector<int>(m, -1)); vector<vector<pii>> prev(n, vector<pii>(m, {-1, -1})); queue<pii> q; dist[0][0] = 0; q.push({0, 0}); while (!q.empty()) { pii zz = q.front(); q.pop(); int x = zz.first, y = zz.second; if (vis[x][y]) continue; vis[x][y] = 1; for (int i = 0; i < 4; i++) { int nx = x + dx[i], ny = y + dy[i]; if (nx >= 0 && nx < n && ny >= 0 && ny < m && arr[nx][ny] == 1) { if (dist[nx][ny] > dist[x][y] + 1) { dist[nx][ny] = dist[x][y] + 1; q.push({nx, ny}); prev[nx][ny] = {x, y}; prevDir[nx][ny] = dir[i]; //代表到达nx ny这个点是从dir[i]方向转过来的。} } } } if (dist[n-1][m-1] == 1e9) { //代表不能到达。cout << "Just Monika" << endl; return; } string path = ""; int x = n - 1, y = m - 1; while (!(x == 0 && y == 0)) { path += char('0' + prevDir[x][y]); tie(x, y) = prev[x][y]; } reverse(path.begin(), path.end()); cout << path << endl; cout << path.size() << endl;
} signed main() { ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr); int T = 1; while (T--) { solve(); }
}