1. 程式人生 > >第十三次CCF計算機軟體能力認證 題解(臨時版)

第十三次CCF計算機軟體能力認證 題解(臨時版)

前言

剛做完= =第五題寫炸了

先大概講講我的思路,有機會我會寫個完整的題解(估計不可能啦,忙的要死)

這些程式碼都是我比賽時候寫的,不保證正確性

第一題

水題,記錄最後一次的得分即可

#include <cstdio>
using namespace std;
int main() {
    int ans = 0, base = 1, x;
    while (true) {
        scanf("%d", &x);
        if (x == 0) {
            printf("%d\n", ans);
            break;
        }
        else if (x == 1) base = 1;
        else if (base == 1) base = 2;
        else base += 2;
        ans += base;
    }
    return 0;
}

第二題

考慮到兩個球相碰只會變方向,所以模擬球的執行即可

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int a[105], d[105], vis[1005];
int main() {
    int n, L, t;
    scanf("%d%d%d", &n, &L, &t);
    for (int i = 0; i < n; i++) {
        scanf("%d", &a[i]);
        d[i] = 1;
    }
    for (int i = 1; i <= t; i++) {
        memset(vis, -1, sizeof(vis));
        for (int j = 0; j < n; j++) {
            a[j] += d[j];
            if (vis[a[j]] != -1) swap(d[j], d[vis[a[j]]]);
            else vis[a[j]] = j;
            if (a[j] == 0) d[j] = 1;
            if (a[j] == L) d[j] = -1;
        }
    }
    for (int i = 0; i < n; i++) {
        printf("%d%c", a[i], i == n - 1 ? '\n' : ' ');
    }
    return 0;
}

第三題

按照題意理解,會發現只需要考慮三種匹配的情況即可。

#include <iostream>
#include <string>
#include <vector>
using namespace std;
string S, R, rule[105], name[105], str;
vector<string> ans;
int L[105];
int main() {
    int n, m, len, rule_pos, str_pos;
    bool error, flag;
    cin >> n >> m;
    for (int i = 0; i < n; i++) {
        cin >> rule[i] >> name[i];
        L[i] = rule[i].length();
    }
    for (int i = 0; i < m; i++) {
        flag = false;
        cin >> str;
        len = str.length();
        for (int j = 0; j < n; j++) {
            //cout << "Here is rule NO." << j << endl;
            ans.clear();
            rule_pos = 0, str_pos = 0, error = false;
            while (str_pos < len && rule_pos < L[j]) {
                //cout << "At str_pos = " << str_pos << " , rule_pos = " << rule_pos << endl;
                if (rule[j][rule_pos] == '<') {
                    rule_pos++;
                    R.clear();
                    while (rule[j][rule_pos] != '>') {
                        R += rule[j][rule_pos];
                        rule_pos++;
                    }
                    rule_pos++;
                    if (R == "int") {
                        S.clear();
                        while (true) {
                            if (str_pos == len) {
                                if (S.length() == 0) {
                                    error = true;
                                }
                                break;
                            }
                            if (str[str_pos] == '/') {
                                if (S.length() == 0) {
                                    error = true;
                                }
                                break;
                            }
                            else if (str[str_pos] >= '0' && str[str_pos] <= '9') {
                                S += str[str_pos];
                                str_pos++;
                            }
                            else {
                                error = true;
                                break;
                            }
                        }
                        if (error) break;
                        if (S.find_first_not_of('0') == string::npos) ans.push_back("0");
                        else {
                            S = S.substr(S.find_first_not_of('0'));
                            ans.push_back(S);
                        }
                    }
                    else if (R == "str") {
                        S.clear();
                        while (true) {
                            if (str_pos == len) {
                                if (S.length() == 0) {
                                    error = true;
                                }
                                break;
                            }
                            if (str[str_pos] == '/') {
                                if (S.length() == 0) {
                                    error = true;
                                }
                                break;
                            }
                            else if (str[str_pos] >= '0' && str[str_pos] <= '9') {
                                S += str[str_pos];
                                str_pos++;
                            }
                            else if (str[str_pos] == '-') {
                                S += str[str_pos];
                                str_pos++;
                            }
                            else if (str[str_pos] == '_') {
                                S += str[str_pos];
                                str_pos++;
                            }
                            else if (str[str_pos] == '.') {
                                S += str[str_pos];
                                str_pos++;
                            }
                            else if (str[str_pos] >= 'a' && str[str_pos] <= 'z') {
                                S += str[str_pos];
                                str_pos++;
                            }
                            else if (str[str_pos] >= 'A' && str[str_pos] <= 'Z') {
                                S += str[str_pos];
                                str_pos++;
                            }
                            else {
                                error = true;
                                break;
                            }
                        }
                        if (error) break;
                        ans.push_back(S);
                    }
                    else {
                        S.clear();
                        while (true) {
                            if (str_pos == len) {
                                if (S.length() == 0) {
                                    error = true;
                                }
                                break;
                            }
                            if (str[str_pos] == '/') {
                                S += str[str_pos];
                                str_pos++;
                            }
                            else if (str[str_pos] >= '0' && str[str_pos] <= '9') {
                                S += str[str_pos];
                                str_pos++;
                            }
                            else if (str[str_pos] == '-') {
                                S += str[str_pos];
                                str_pos++;
                            }
                            else if (str[str_pos] == '_') {
                                S += str[str_pos];
                                str_pos++;
                            }
                            else if (str[str_pos] == '.') {
                                S += str[str_pos];
                                str_pos++;
                            }
                            else if (str[str_pos] >= 'a' && str[str_pos] <= 'z') {
                                S += str[str_pos];
                                str_pos++;
                            }
                            else if (str[str_pos] >= 'A' && str[str_pos] <= 'Z') {
                                S += str[str_pos];
                                str_pos++;
                            }
                            else {
                                error = true;
                                break;
                            }
                        }
                        if (error) break;
                        ans.push_back(S);
                    }
                }
                else {
                    if (rule[j][rule_pos] != str[str_pos]) {
                        error = true;
                        break;
                    }
                    str_pos++;
                    rule_pos++;
                }
            }
            if (str_pos < len || rule_pos < L[j]) error = true;
            if (!error) {
                cout << name[j];
                for (int m = 0; m < ans.size(); m++) cout << " " << ans[m];
                cout << endl;
                flag = true;
                break;
            }
        }
        if (!flag) cout << "404" << endl;
    }
    return 0;
}

第四題

下棋的情況最多9!種,暴力列舉所有情況即可

#include <cstdio>
#include <algorithm>
using namespace std;
int mp[5][5];
int judge() {
    int cnt = 0;
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            if (mp[i][j] == 0) cnt++;
        }
    }
    for (int d = 1; d <= 2; d++) {
        for (int i = 0; i < 3; i++) {
            bool flag = true;
            for (int j = 0; j < 3; j++) {
                flag = (flag && (mp[i][j] == d));
            }
            if (flag) {
                if (d == 1) return cnt + 1;
                else return -cnt - 1;
            }
        }
    }
    for (int d = 1; d <= 2; d++) {
        for (int j = 0; j < 3; j++) {
            bool flag = true;
            for (int i = 0; i < 3; i++) {
                flag = (flag && (mp[i][j] == d));
            }
            if (flag) {
                if (d == 1) return cnt + 1;
                else return -cnt - 1;
            }
        }
    }
    for (int d = 1; d <= 2; d++) {
        bool flag = true;
        for (int i = 0; i < 3; i++) {
            flag = (flag && (mp[i][i] == d));
        }
        if (flag) {
            if (d == 1) return cnt + 1;
            else return -cnt - 1;
        }
    }
    for (int d = 1; d <= 2; d++) {
        bool flag = true;
        for (int i = 0; i < 3; i++) {
            flag = (flag && (mp[i][2 - i] == d));
        }
        if (flag) {
            if (d == 1) return cnt + 1;
            else return -cnt - 1;
        }
    }
    return 0;
}
int dfs(int cnt, bool flag) {
    int ans;
    if (flag) ans = -10;
    else ans = 10;
    int X = judge();
    if (X != 0) return X;
    if (cnt == 9) return X;
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            if (mp[i][j] == 0) {
                if (flag) mp[i][j] = 1;
                else mp[i][j] = 2;
                if (flag) ans = max(ans, dfs(cnt + 1, !flag));
                else ans = min(ans, dfs(cnt + 1, !flag));
                mp[i][j] = 0;
            }
        }
    }
    return ans;

}
int main() {
    int T, cnt;
    scanf("%d", &T);
    while (T--) {
        cnt = 0;
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                scanf("%d", &mp[i][j]);
                if (mp[i][j] != 0) cnt++;
            }
        }
        printf("%d\n", dfs(cnt, true));
    }
    return 0;
}

第五題

考慮到每次操作只是對一條鏈加一個值,所以我們可以預處理出每個節點對答案的貢獻倍數,然後每次記錄答案,那麼我們就不需要更新節點值,而是直接在答案上加。

我寫的是n^2預處理貢獻,mlognlogn進行計算答案,可惜寫炸了。。。

貌似100%的通過需要用樹分治預處理貢獻

以下的程式碼是寫炸的,等到cspro把題掛出來了我再嘗試改正吧= =||

#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define ms(x) memset(x, 0, sizeof(x))
typedef vector<int> vi;
typedef long long ll;
const ll MOD = 1e9 + 7;
const int MAX_N = 2e3 + 5;
vi mp[MAX_N];
int Size[MAX_N], pre[MAX_N], depth[MAX_N], Top[MAX_N], ID[MAX_N], son[MAX_N], tot, n, lmtL, lmtR;
ll w[MAX_N], a[MAX_N];
//map<int, int> num[MAX_N];
struct Segment_Tree {
    struct Node {
        ll seg;
    } T[MAX_N << 2];
    void push_up(int rt) {
        T[rt].seg = (T[rt << 1].seg + T[rt << 1 | 1].seg) % MOD;
    }
    void Build(int l, int r, int rt) {
        T[rt].seg = 0;
        if (l == r) {
            T[rt].seg = 0;
            return;
        }
        int m = (l + r) >> 1;
        Build(lson), Build(rson), push_up(rt);
    }
    void Update(int pos, ll c, int l, int r, int rt) {
        if (l == r) {
            T[rt].seg = c;
            return;
        }
        int m = (l + r) >> 1;
        if (pos <= m) Update(pos, c, lson);
        if (pos > m) Update(pos, c, rson);
        push_up(rt);
    }
    ll Query(int L, int R, int l, int r, int rt) {
        if (L > R) return -1;
        if (L <= l && r <= R) return T[rt].seg;
        int m = (l + r) >> 1;
        ll ret = 0;
        if (L <= m) ret = (ret + Query(L, R, lson)) % MOD;
        if (m < R) ret = (ret + Query(L, R, rson)) % MOD;
        return ret;
    }
} ST;
void init_HLD(int x, int dad) {
    Size[x] = 1, pre[x] = dad;
    for (int i = 0; i < mp[x].size(); i++) {
        int y = mp[x][i];
        if (y == dad) continue;
        depth[y] = depth[x] + 1;
        init_HLD(y, x);
        Size[x] += Size[y];
        if (Size[y] > Size[son[x]]) son[x] = y;
    }
}
void HLD(int x, int Tp) {
    Top[x] = Tp, tot++;
    ID[x] = tot;
    ST.Update(ID[x], w[x], 1, n, 1);
    if (son[x] > 0) HLD(son[x], Tp);
    for (int i = 0; i < mp[x].size(); i++) {
        int y = mp[x][i];
        if (y == pre[x]) continue;
        if (y == son[x]) continue;
        HLD(y, y);
    }
}
ll Query(int x, int y) {
    int X = Top[x], Y = Top[y];
    ll ans = 0;
    while (X != Y) {
        if (depth[X] < depth[Y]) swap(X, Y), swap(x, y);
        ans = (ans + ST.Query(ID[x], ID[y], 1, n, 1)) % MOD;
        x = pre[X], X = Top[x];
    }
    if (depth[x] > depth[y]) swap(x, y);
    ans = (ans + ST.Query(ID[x], ID[y], 1, n, 1)) % MOD;
    //printf("Query(%d, %d) = %lld\n", x, y, ans);
    return ans;
}
void HLD_INIT(int root) {
    ms(son), tot = 0, depth[root] = 0;
    init_HLD(root, 0);
    HLD(root, root);
}
ll dfs(int x, int dad, int d) {
    ll ans = 0;
    if (d >= lmtL && d <= lmtR) ans++;
    for (int i = 0; i < mp[x].size(); i++) {
        int y = mp[x][i];
        if (y == dad) continue;
        ans = (ans + dfs(y, x, d + 1)) % MOD;
    }
    w[x] = (ans + w[x]) % MOD;
    return ans;
}
int main() {
    int T, m, x, u, v;
    ll ans, d;
    scanf("%d", &T);
    while (T--) {
        ms(w), ms(a), ans = 0;
        scanf("%d%d%d%d", &n, &m, &lmtL, &lmtR);
        for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
        for (int i = 2; i <= n; i++) {
            scanf("%d", &x);
            mp[x].push_back(i);
            mp[i].push_back(x);
        }
        for (int i = 1; i <= n; i++) {
            dfs(i, 0, 1);
            ans = (ans + w[i] * a[i] % MOD) % MOD;
        }
        for (int j = 1; j <= n; j++) w[j] /= 2;
        ST.Build(1, n, 1);
        HLD_INIT(1);
        //printf("ans = %lld\n", ans);
        while (m--) {
            scanf("%d%d%lld", &u, &v, &d);
            ans = (ans + Query(u, v) * d % MOD) % MOD;
            printf("%lld\n", ans);
        }
    }
    return 0;
}