AtCoder Beginner Contest 363

AtCoder Beginner Contest 363

前言

只出了三题,被 d 卡住了,事实上 e 题应该对我而言更简单,没及时换题。

A - Piling Up (atcoder.jp)

思路

代码

#include<bits/stdc++.h>

using namespace std;

using i64 = long long;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int R;
    cin >> R;

    if (R <= 99) cout << 100 - R << '\n';
    else if (R <= 199)cout << 200 - R << '\n';
    else cout << 300 - R << '\n';

    return 0;
}

B - Japanese Cursed Doll (atcoder.jp)

思路

问第 P 小的数比 T 差多少。

代码

#include<bits/stdc++.h>

using namespace std;

using i64 = long long;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int N, T, P;
    cin >> N >> T >> P;

    vector<int> L(N + 1);
    for (int i = 1; i <= N; i ++) {
        cin >> L[i];
    }

    sort(L.begin() + 1, L.end());

    cout << max(T - L[N - P + 1], 0) << '\n';

    return 0;
}

C - Avoid K Palindrome 2 (atcoder.jp)

思路

全排列判一下回文串即可。

代码

#include<bits/stdc++.h>

using namespace std;

using i64 = long long;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int N, K;
    cin >> N >> K;

    string s;
    cin >> s;

    sort(s.begin(), s.end());

    int ans = 0;

    do {
        int f = 1;
        for (int i = 0; i + K - 1 < N; i ++) {
            int l = i, r = i + K - 1;
            while (l <= r && s[l] == s[r])
                l ++, r--;
            if (r < l) {
                f = 0;
            }
        }
        ans += f;
    } while (next_permutation(s.begin(), s.end()));

    cout << ans << '\n';

    return 0;
}

D - Palindromic Number (atcoder.jp)

题意

问第 N 大的数字回文串是多少。

思路

除 0 以外,枚举位数观察回文数的分布,1 位的回文数有 9 个,2 位的回文数有 9 个,3 位的回文数有 90 个,4 位的回文数有 90 个,5 位的回文数有 900 个,6 位的回文数有 900 个,7 位的回文数有 9000 个,8 位的回文数有 9000 个 \(\dots\),所以我们可以快速枚举 N 位,看它定位在哪位数,由于最高位非 0 ,所以 N 需要减 1 在最高位来放置至少一个 1 ,剩下的就是从 这一位开始找第 \(m(N\%p)\) 小的自然数,此时我们只是确定了这个回文数的一半,根据以上的性质,每 \(9\times 10^x\) 个数是有奇数位和偶数位分布的,所以我们需要判断一下当前 N 是否小于 \(9\times 10^x\) ,是的话就是奇数位的,需要去掉最后一位。

代码

#include<bits/stdc++.h>

using namespace std;

using i64 = long long;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    i64 N;
    cin >> N;

    if (N == 1) {
        cout << 0 << '\n';
        return 0;
    }

    N --;

    i64 p = 9;
    while (N >= 2 * p) {
        N -= 2 * p;
        p *= 10;
    }

    N --;

    string s = to_string(N % p + p / 9);
    string t = s;

    reverse(t.begin(), t.end());

    if (N < p) {
        s.pop_back();
    }
    s += t;
    cout << s << '\n';

    return 0;
}

E - Sinking Land (atcoder.jp)

思路

bfs + 优先队列。

先把临海的点加进最小堆里,其他待加入的点标记一下,每次海平面高过最低点后就向四周搜一下,把没加入的点加进去。

代码

#include<bits/stdc++.h>

using namespace std;

using i64 = long long;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int H, W, Y;
    cin >> H >> W >> Y;

    set<pair<int, int>> st;
    vector mp(H + 1, vector<int>(W + 1));
    priority_queue<array<int, 3>> Q;
    for (int i = 1; i <= H; i ++) {
        for (int j = 1; j <= W; j ++) {
            cin >> mp[i][j];
            if (i == 1 || i == H || j == 1 || j == W) {
                Q.push({ -mp[i][j], i, j});
            } else {
                st.insert({i, j});
            }
        }
    }

    const int u[] = {0, 0, 1, -1}, v[] = {1, -1, 0, 0};

    int ans = H * W;
    for (int y = 1; y <= Y; y ++) {

        while (Q.size()) {
            auto [val, i, j] = Q.top();
            val = -val;
            if (val > y) break;
            Q.pop();

            ans --;
            for (int k = 0; k < 4; k ++) {
                int dx = i + u[k], dy = j + v[k];
                if (dx >= 1 && dx <= H && dy >= 1 && dy <= W) {
                    if (!st.count({dx, dy})) continue;
                    Q.push({ -mp[dx][dy], dx, dy});
                    st.erase({dx, dy});
                }
            }
        }

        cout << ans << '\n';
    }

    return 0;
}
posted @ 2024-07-23 20:31  Ke_scholar  阅读(24)  评论(0编辑  收藏  举报