1. 程式人生 > 其它 >上海市計算機學會競賽平臺2020年3月月賽(丙組題目)題解

上海市計算機學會競賽平臺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;
}