ZZJC新生训练赛第二十场题解

链接:https://vjudge.net/contest/677776
密码:ZZJCACM

A-解题思路

(800)按照题意模拟,map存一下两两配对看有多少即可

A-代码实现

from collections import Counter
for _ in range(int(input())):
    n = int(input())
    a = list(map(int, input().split()))
    c = Counter(a)
    ans = 0
    for i, j in c.items():
        ans += j // 2
    print(ans)

B-解题思路

(1300)赤石题,按照题意模拟每一次层就行,注意答案可能来自尾部和首部的拼接

B-代码实现

#include <bits/stdc++.h>

using i64 = long long;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);

    int t;
    std::cin >> t;

    while (t--) {
        int n, m;
        std::cin >> n >> m;

        std::vector<std::vector<char>> g(n, std::vector<char>(m));
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                std::cin >> g[i][j];
            }
        }

        int ans = 0;
        for (int i = 0; i < std::min(n / 2, m / 2); i++) {
            int x1 = i, y1 = i;
            int x2 = i, y2 = m - i - 1;
            int x3 = n - i - 1, y3 = m - i - 1;
            int x4 = n - i - 1, y4 = i;
            // std::cout << x1 << " " << y1 << " " << x2 << " " << y2 << " " << x3 << " " << y3 << " " << x4 << " " << y4 << "\n";

            int siz = 0;
            std::string s;
            for (int x = x1, y = y1; y <= y2; y++) {
                s += g[x][y];
                siz++;
            }

            for (int x = x2 + 1, y = y2; x <= x3; x++) {
                s += g[x][y];
                siz++;
            }

            for (int x = x3, y = y3 - 1; y >= y4; y--) {
                s += g[x][y];
                siz++;
            }

            for (int x = x4 - 1, y = y4; x > x1; x--) {
                s += g[x][y];
                siz++;
            }

            s += s;

            for (int j = 0; j < siz; j++) {
                ans += s.substr(j, 4) == "1543";
            }
        }

        std::cout << ans << "\n";
    }
}

C-解题思路

(1000)人机构造题,乱搞一下就能发现至少要五个,然后根据奇偶放两侧就行

C-代码实现

for _ in range(int(input())):
    n = int(input())
    if n <= 4:
        print(-1)
    else:
        l = []
        r = []
        mid = [3, 1, 5, 4, 2]
        for i in range(6, n + 1):
            if i % 2:
                l.append(i)
            else:
                r.append(i)
        print(*(l + mid + r))

D-解题思路

(1600)构造+交互,对于位置pos的询问显然满足如果pos和pos-1的答案相同则pos是0,否则pos是1。因此从最右侧一直往左边扫过去直到回答是0就能知道右侧的构成,此时需要回溯到上一次回答,要在左侧填充对应数量的0,剩余部分全填1即可

D-代码实现

#include <bits/stdc++.h>

int main() {
    int t;
    std::cin >> t;

    while (t--) {
        int n, f = 1, p = -1;
        std::cin >> n;

        if (n < 2) {
            std::cout << "! IMPOSSIBLE" << std::endl;
            continue;
        }

        std::string s;
        for (int i = n; i >= 2; i--) {
            std::cout << "? " << 1 << " " << i << std::endl;
            std::cin >> f;
            if (!f) {
                break;
            }
            if (p == -1) {
                p = f;
            } else {
                if (p == f) {
                    s = "0" + s;
                } else {
                    p = f;
                    s = "1" + s;
                }
            }
        }

        s = "1" + s;
        if (p == -1) {
            std::cout << "! IMPOSSIBLE" << std::endl;
        } else {
            for (int i = 0; i < p; i++) {
                s = "0" + s;
            }
            for (int i = s.size(); i < n; i++) {
                s = "1" + s;
            }
            std::cout << "! " << s << std::endl;
        }
    }
}

E-解题思路

(800)用k的两个因数构造就行

E-代码实现

#include <bits/stdc++.h>

using i64 = long long;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);

    int t;
    std::cin >> t;

    while (t--) {
        int k;
        std::cin >> k;
        k -= 2;

        std::vector<int> a(k + 2);
        std::map<int, int> mp;
        for (int i = 0; i < k + 2; i++) {
            std::cin >> a[i];
            mp[a[i]]++;
        }

        for (auto i : a) {
            if (k % i == 0 && (mp.count(k / i) && i != k / i || k / i == i && mp[i] >= 2)) {
                std::cout << i << " " << k / i << "\n";
                break;
            }
        }
    }
}

F-解题思路

(800)同品牌合并取最大的n个即可

F-代码实现

#include <bits/stdc++.h>

using i64 = long long;

int main() {
    std::ios::sync_with_stdio(0);
    std::cin.tie(0);
    std::cout.tie(0);

    int t;
    std::cin >> t;

    while (t--) {
        int n, k;
        std::cin >> n >> k;

        std::map<int, i64> mp;
        for (int i = 0; i < k; i++) {
            int b, c;
            std::cin >> b >> c;

            mp[b] += c;
        }

        std::vector<i64> v;
        for (auto [x, y] : mp) {
            v.push_back(y);
        }

        std::sort(v.begin(), v.end(), std::greater<>());

        i64 ans = 0;
        for (int i = 0; i < n && i < (int)v.size(); i++) {
            ans += v[i];
        }

        std::cout << ans << "\n";
    }
}

G-解题思路

(1100)统计修改前后目标串的数量即可

G-代码实现

#include <bits/stdc++.h>

using i64 = long long;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);

    int t;
    std::cin >> t;

    while (t--) {
        std::string s;
        std::cin >> s;

        int q;
        std::cin >> q;

        int cnt = 0;
        for (int i = 0; i + 3 < s.size(); i++) {
            if (s.substr(i, 4) == "1100") {
                cnt++;
            }
        }

        while (q--) {
            int i, v;
            std::cin >> i >> v;

            i--;

            for (int j = std::max(0, i - 3); j <= i && j + 3 < s.size(); j++) {
                if (s.substr(j, 4) == "1100") {
                    cnt--;
                }
            }

            s[i] = v + '0';

            for (int j = std::max(0, i - 3); j <= i && j + 3 < s.size(); j++) {
                if (s.substr(j, 4) == "1100") {
                    cnt++;
                }
            }

            if (cnt) {
                std::cout << "YES\n";
            } else {
                std::cout << "NO\n";
            }
        }
    }

    return 0;
}

H-解题思路

(1600)枚举最后一场电影的位置减去对应的d(到i场就会有固定i*d个间隔),优先队列贪心地选择m个最大正数即可

H-代码实现

#include <bits/stdc++.h>

using i64 = long long;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);

    int t;
    std::cin >> t;

    while (t--) {
        i64 n, m, d;
        std::cin >> n >> m >> d;

        i64 ans = 0, sum = 0;
        std::priority_queue<i64, std::vector<i64>, std::greater<>> pq;
        for (int i = 1; i <= n; i++) {
            int x;
            std::cin >> x;

            if (x > 0) {
                pq.push(x);
                sum += x;
            }
            while (pq.size() > m) {
                sum -= pq.top();
                pq.pop();
            }

            ans = std::max(ans, sum - i * d);
        }

        std::cout << ans << "\n";
    }
}

I-解题思路

(1600)一种简单的思路是让最小生成树就是最短路,让权重和为第一个不小于m的质数,可用一堆1和一个剩余的数字来构成这个质数,暴力枚举没用过的边全都设为无穷大让他们不能选即可

I-代码实现

#include <bits/stdc++.h>

const int N = 1e6 + 10;
const int INF = 1e9;

std::vector<int> primes;
bool f[N];

void euler(int n) {
    for (int i = 2; i <= n; i++) {
        if (!f[i]) {
            primes.push_back(i);
        }
        for (int prime : primes) {
            if (i * prime > n) {
                break;
            }
            f[i * prime] = true;
            if (i % prime == 0) {
                break;
            }
        }
    }
}

int main() {
    std::ios::sync_with_stdio(0);
    std::cin.tie(0);
    std::cout.tie(0);

    euler(N);

    int n, m;
    std::cin >> n >> m;

    int ans = *std::lower_bound(primes.begin(), primes.end(), m);
    std::cout << ans << " " << ans << "\n";

    std::set<std::array<int, 2>> st;
    for (int i = 1; i <= n - 2; i++) {
        std::cout << i << " " << i + 1 << " " << 1 << "\n";
        st.insert({i, i + 1});
    }
    std::cout << n - 1 << " " << n << " " << ans - n + 2 << "\n";
    st.insert({n - 1, n});

    m -= n - 1;
    if (m == 0) {
        return 0;
    }
    for (int i = 1; i <= n; i++) {
        for (int j = i + 1; j <= n; j++) {
            if (!st.count({i, j})) {
                std::cout << i << " " << j << " " << INF << "\n";
                st.insert({i, j});
                m--;
                if (m == 0) {
                    return 0;
                }
            }
        }
    }
}
posted @ 2024-12-05 22:31  udiandianis  阅读(39)  评论(0)    收藏  举报