AtCoder Regular Contest 094 – 解题报告

说实话这绝对是我做过最垃圾的一套 ARC 了,没有之一。

D – Worst Case

这个题有点像我之前 Codeforces 做过的一个题,但是好像不是一样的,所以被卡了好久。

首先考虑几个特判,我们先设 \(A < B\):

  • \(A = B\),这个答案就是 \(2(A – 1)\),没什么好说的。
  • \(A = B – 1\),这个的话答案也是 \(2(A – 1)\),没什么好说的。

之后考虑 \(A < B – 1\) 的情况了。首先他们的这个积最后是 \(A\times B\)。我们要数清楚有多少个 \((x, y), x \times y < A \times B\)。其实想到这里可以尝试找一个 \(C\) 使得 \(C^2 < AB\)。这个时候一般会存在 \(A < C < B\) 的情况。如果 \(C(C + 1) < AB\) 那么答案为 \(2C – 1\),否则为 \(2C – 2\)。

发现其实 \(C(C + 1)\) 其实是一组解,所以我们先来思考为什么答案是 \(2C – 2\)。可以考虑构造 \((1, A + B – 1), (2, A + B), \dots, (A – 1, B + 1), (A + 1, 2C – A – 1), \dots, (C, C), \dots (2C, 1)\)。

// ARC094B.cpp
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

ll Q, n = 1e12, a, b;

int main()
{
    scanf("%lld", &Q);
    while (Q--)
    {
        scanf("%lld%lld", &a, &b);
        if (a > b)
            swap(a, b);
        ll ans = 0;
        if (a == b || a + 1 == b)
            ans += 2LL * a - 2;
        else
        {
            ll C = sqrt(1LL * a * b) - 1;
            while ((C + 1) * (C + 1) < 1LL * a * b)
                C++;
            if (C * (C + 1) >= 1LL * a * b)
                ans = 2LL * C - 2;
            else
                ans = 2LL * C - 1;
        }
        printf("%lld\n", ans);
    }
    return 0;
}

E – Tozan and Gezan

Tozan 可以直接随心所欲的走,而 Gezan 并不能进行有效的抑制。最后情况一定会是 \(0, 0, 0, 0, \dots, b_i, 0, \dots\)。所以最后 Candy 计数肯定会把所有的 \(a_i\) 计入,但是除了中间的 \(b_i\)。这个 \(b_i\) 取 \(a_i > b_i\) 时的最小值,因为只有这个情况会出现在最后状态下。

// ARC094C.cpp
#include <bits/stdc++.h>

using namespace std;

const int MAX_N = 2e5 + 200;

typedef pair<int, int> pii;

int n, ai[MAX_N], bi[MAX_N];
priority_queue<pii> pq1;
multiset<pii> pq2;

int main()
{
    scanf("%d", &n);
    long long ans = 0, acc = 1LL << 30;
    bool flag = true;
    for (int i = 1; i <= n; i++)
    {
        scanf("%d%d", &ai[i], &bi[i]);
        flag &= (ai[i] == bi[i]), ans += ai[i];
        if (ai[i] > bi[i])
            acc = min(acc, 1LL * bi[i]);
    }
    if (flag)
        puts("0");
    else
        printf("%lld\n", ans - acc);
    return 0;
}

F – Normalization

就是这个题让整套题都很烂了(

想半天去看个题解,最后发现是个结论题,而且没有任何证明(四色定理式证明),我是佛了。

// ARC094D.cpp
#include <bits/stdc++.h>

using namespace std;

const int MAX_N = 2e5 + 200, mod = 998244353;

int n, dp[MAX_N][3][3][2], str[MAX_N];
char org[MAX_N];

int main()
{
    scanf("%s", org + 1), n = strlen(org + 1);
    int oddity = 0, tot[3] = {0, 0, 0};
    bool flag = true;
    for (int i = 1; i <= n; i++)
        str[i] = org[i] - 'a', oddity = (oddity + str[i]) % 3, tot[str[i]]++;
    for (int i = 1; i < n; i++)
        flag &= (str[i] != str[i + 1]);
    if (tot[0] == n || tot[1] == n || tot[2] == n)
        puts("1"), exit(0);
    if (n <= 3)
    {
        map<string, bool> mp;
        string org_str = org + 1;
        mp[org_str] = true;
        int delta = 0;
        do
        {
            delta = 0;
            for (auto x : mp)
                for (int i = 0; i < n - 1; i++)
                    if (x.first[i] != x.first[i + 1])
                    {
                        string nxt = x.first;
                        nxt[i] = nxt[i + 1] = ('a' ^ 'b' ^ 'c') ^ (x.first[i] ^ x.first[i + 1]);
                        if (mp[nxt] == false)
                            mp[nxt] = true, delta++;
                    }
        } while (delta);
        printf("%lld\n", 1LL * mp.size());
    }
    else
    {
        int ans = (flag == true);
        dp[1][0][0][0] = dp[1][1][1][0] = dp[1][2][2][0] = 1;
        for (int i = 2; i <= n; i++)
            for (int sum = 0; sum < 3; sum++)
                for (int pre = 0; pre < 3; pre++)
                    for (int curt = 0; curt < 3; curt++)
                        if (pre == curt)
                            dp[i][(sum + curt) % 3][curt][1] = (0LL + dp[i][(sum + curt) % 3][curt][1] + dp[i - 1][sum][pre][0] + dp[i - 1][sum][pre][1]) % mod;
                        else
                        {
                            dp[i][(sum + curt) % 3][curt][0] = (0LL + dp[i][(sum + curt) % 3][curt][0] + dp[i - 1][sum][pre][0]) % mod;
                            dp[i][(sum + curt) % 3][curt][1] = (0LL + dp[i][(sum + curt) % 3][curt][1] + dp[i - 1][sum][pre][1]) % mod;
                        }
        for (int i = 0; i < 3; i++)
            ans = (0LL + ans + dp[n][oddity][i][1]) % mod;
        printf("%d\n", ans);
    }

    return 0;
}

Leave a Reply

Your email address will not be published. Required fields are marked *