上海市计算机学会竞赛平台2020年3月月赛(丙组题目)题解
比赛链接:https://iai.sh.cn/contest/3
T1 打渔还是晒网
题目链接:https://iai.sh.cn/problem/17
解题思路:
数学题。可以发现周期是 \(5\) 天,所以判断 \(n\) 除以 \(5\) 的余数是不是 \(1,2,3\) 即可。实际解决时我是使用 (n-1)%5<3
来判断的。
示例程序:
#include <bits/stdc++.h>
using namespace std;
int n;
int main() {
cin >> n;
puts((n-1)%5 < 3 ? "Fishing" : "Lying");
}
T2 数字加密
题目链接:https://iai.sh.cn/problem/14
解题思路:
简单字符串模拟题。按照题目的反过程还原原来的字符串即可。
示例程序:
#include <bits/stdc++.h>
using namespace std;
char s[5];
void t(char &c) {
int a = c - '0';
c = '0' + 9 - a;
}
int main() {
cin >> s;
for (int i = 0; i < 4; i ++) t(s[i]);
for (int i = 0; i < 2; i ++) swap(s[i], s[3-i]);
puts(s);
return 0;
}
T3 双质数
题目链接:https://iai.sh.cn/problem/11
解题思路:
函数+循环。考查函数的应该和循环。注意:判断素数得用 \(O(\sqrt a)\) 的方法,或者使用素数筛法。
示例程序1(\(O(\sqrt a)\) 判素数):
#include <bits/stdc++.h>
using namespace std;
bool check(int a) {
if (a < 2) return false;
for (int i = 2; i*i <= a; i ++)
if (a % i == 0)
return false;
return true;
}
int a, b;
bool flag;
int main() {
cin >> a >> b;
for (int i = a; i <= b; i ++) {
if (check(i) && check(i/10)) {
flag = true;
cout << i << endl;
}
}
if (!flag)
puts("None");
return 0;
}
示例程序2(素数筛法):
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1000010;
int a, b;
bool flag, f[maxn];
void init() {
f[0] = f[1] = true;
for (int i = 2; i < maxn; i ++)
if (!f[i])
for (int j = i+i; j < maxn; j += i)
f[j] = true;
}
int main() {
init();
cin >> a >> b;
for (int i = a; i <= b; i ++) {
if (!f[i] && !f[i/10]) {
flag = true;
cout << i << endl;
}
}
if (!flag)
puts("None");
return 0;
}
T4 连乘问题
题目链接:https://iai.sh.cn/problem/13
解题思路:
方法1: 动态规划 递推,求解前缀和后缀。\(f[i]\) 表示前 \(i\) 个数的乘积 \(\mod 10000\) 的结果。\(g[i]\) 表示 \(a_i\) 到 \(a_n\) 的成绩 \(\mod 10000\) 的结果。
方法2:扩展GCD求解矩阵的逆。
示例程序(方法1):
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100010;
int n, a[maxn], f[maxn], g[maxn];
const int MOD = 10000;
int main() {
cin >> n;
for (int i = 1; i <= n; i ++) cin >> a[i];
f[0] = 1;
for (int i = 1; i <= n; i ++) f[i] = f[i-1] * a[i] % MOD;
g[n+1] = 1;
for (int i = n; i >= 1; i --) g[i] = g[i+1] * a[i] % MOD;
for (int i = 1; i <= n; i ++)
cout << f[i-1] * g[i+1] % MOD << endl;
return 0;
}
T5 救援争先
题目链接:https://iai.sh.cn/problem/15
解题思路:
结构体排序。稍微要注意一下处理输入格式。
示例程序:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1010;
struct Node {
int sh, sm, st, dh, dm, et, id;
} a[maxn];
bool cmp(Node a, Node b) {
return a.et<b.et || a.et==b.et && a.st<b.st || a.et==b.et && a.st==b.st && a.id<b.id;
}
int n;
int main() {
scanf("%d", &n);
for (int i = 0; i < n; i ++) {
scanf("%d:%d %d:%d", &a[i].sh, &a[i].sm, &a[i].dh, &a[i].dm);
a[i].st = a[i].sh * 60 + a[i].sm;
a[i].et = a[i].st + a[i].dh * 60 + a[i].dm;
a[i].id = i+1;
}
sort(a, a+n, cmp);
for (int i = 0; i < n; i ++)
printf("%d\n", a[i].id);
return 0;
}