Loading [MathJax]/extensions/tex2jax.js

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)\)。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// 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;
}
// 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; }
// 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\) 时的最小值,因为只有这个情况会出现在最后状态下。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// 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;
}
// 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; }
// 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

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

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// 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;
}
// 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; }
// 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 *