UNIQUE VISION Programming Contest 2023 Christmas (AtCoder Beginner Contest 334)

发布时间 2023-12-26 02:41:34作者: value0

UNIQUE VISION Programming Contest 2023 Christmas (AtCoder Beginner Contest 334)

A - Christmas Present

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 310;
typedef pair<ll, ll> pii;
typedef pair<pii, ll> piii;
#define fi first
#define se second
const int mod = 1e9 + 7;

void solve()
{
    int a, b;
    cin >> a >> b;
    if (a > b)
    {
        puts("Bat");
    }
    else
    {
        puts("Glove");
    }
}

int main()
{
    int t = 1;
    while (t--)
    {
        solve();
    }
    return 0;
}

B - Christmas Trees

解题思路:

三种情况:

  • \(l \leq a \leq r\)
  • \(a \leq l \leq r\)
  • \(l \leq r \leq a\)

注意点:\((0,3,6,9)\):\(\frac{6 - 0}{3} = 2\),\(\frac{9 - 0}{3} = 3\),\(3 - 2 = 1\),但答案是\(2\)

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 310;
typedef pair<ll, ll> pii;
typedef pair<pii, ll> piii;
#define fi first
#define se second
const int mod = 1e9 + 7;

void solve()
{
    ll a, m, l, r;
    cin >> a >> m >> l >> r;
    ll ans = 0;
    if (l <= a && r >= a)
    {
        ans += (a - l) / m + (r - a) / m + 1;
    }
    else if (l >= a && r >= a)
    {
        ans = (r - a) / m - ((l - 1) - a) / m + (l == a ? 1 : 0);
    }
    else if (l <= a && r <= a)
    {
        ans = (a - l) / m - (a - (r + 1)) / m + (r == a ? 1 : 0);
    }
    cout << ans << endl;
}

int main()
{
    int t = 1;
    while (t--)
    {
        solve();
    }
    return 0;
}

C - Socks 2

解题思路:

贪心地想,位置靠的近的优先配对。

如果单只的袜子的个数是偶数个,那么直接升序两两配对。

如果单只的袜子的个数是奇数个,那么必定有一个是无法配对的,我们枚举这个无法配对的单只袜子。

我们发现,如果我们选取第偶数只袜子作为剩下的袜子,一定有一种选取第奇数只袜子作为剩下袜子的选法由于它,所以直接前缀后缀和枚举即可。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 310;
typedef pair<ll, ll> pii;
typedef pair<pii, ll> piii;
#define fi first
#define se second
const int mod = 1e9 + 7;

void solve()
{
    int n, k;
    cin >> n >> k;
    vector<int> a(1);
    for (int i = 1; i <= k; i++)
    {
        int x;
        cin >> x;
        a.push_back(x);
    }
    sort(a.begin() + 1, a.end());
    vector<ll> pre(n + 10, 0), suf(n + 10, 0);
    n = k;
    for (int i = 1; i <= n; i++)
    {
        if (i & 1)
        {
            pre[i] = pre[i - 1];
        }
        else
        {
            pre[i] = pre[i - 1] + (a[i] - a[i - 1]);
        }
    }
    if (!(n & 1))
    {
        cout << pre[n] << endl;
        return;
    }
    for (int i = n; i; i--)
    {
        if (i & 1)
        {
            suf[i] = suf[i + 1];
        }
        else
        {
            suf[i] = suf[i + 1] + (a[i + 1] - a[i]);
        }
    }
    ll ans = 1e18;
    for (int i = 1; i <= n; i++)
    {
        if (i & 1)
        {
            ans = min(ans, pre[i] + suf[i]);
        }
    }
    cout << ans << endl;
}

int main()
{
    int t = 1;
    while (t--)
    {
        solve();
    }
    return 0;
}

D - Reindeer and Sleigh

解题思路:

预处理升序前缀和,对于每个询问直接二分查找匹配答案。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 310;
typedef pair<ll, ll> pii;
typedef pair<pii, ll> piii;
#define fi first
#define se second
const int mod = 1e9 + 7;

void solve()
{
    int n, q;
    cin >> n >> q;
    vector<ll> r(n + 1);
    for (int i = 1; i <= n; i++)
    {
        cin >> r[i];
    }
    sort(r.begin() + 1, r.end());
    vector<ll> s(n + 1);
    for (int i = 1; i <= n; i++)
    {
        s[i] = s[i - 1] + r[i];
    }
    while (q--)
    {
        ll x;
        cin >> x;
        auto it = upper_bound(s.begin() + 1, s.end(), x);
        it--;
        cout << (it - s.begin()) << endl;
    }
}

int main()
{
    int t = 1;
    while (t--)
    {
        solve();
    }
    return 0;
}

E - Christmas Color Grid 1

解题思路:

题目说明很清楚,枚举所有的红色位置,用概率乘以修改后全局的连通块数累加即可。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 310;
typedef pair<ll, ll> pii;
typedef pair<pii, ll> piii;
#define fi first
#define se second
#define int long long
const int mod = 998244353;
int dx[] = {-1, 1, 0, 0};
int dy[] = {0, 0, -1, 1};

ll qmi(ll a, ll b)
{
    ll res = 1;
    while (b)
    {
        if (b & 1)
        {
            res = (res * a) % mod;
        }
        b >>= 1;
        a = (a * a) % mod;
    }
    return res;
}

void solve()
{
    int n, m;
    cin >> n >> m;
    vector<string> g(n + 1);
    for (int i = 1; i <= n; i++)
    {
        cin >> g[i];
        g[i] = ' ' + g[i];
    }
    ll cnt = 0;
    vector<vector<int>> id(n + 1, vector<int>(m + 1));
    vector<vector<bool>> st(n + 1, vector<bool>(m + 1));
    ll uid = 0;
    auto check = [&](int a, int b)
    {
        if (a < 1 || b < 1 || a > n || b > m)
        {
            return false;
        }
        if (st[a][b])
        {
            return false;
        }
        if (g[a][b] == '.')
        {
            return false;
        }
        return true;
    };
    auto dfs = [&](auto self, int x, int y, int cid) -> void
    {
        id[x][y] = cid;
        st[x][y] = true;
        for (int i = 0; i < 4; i++)
        {
            int nx = x + dx[i];
            int ny = y + dy[i];
            if (check(nx, ny))
            {
                self(self, nx, ny, cid);
            }
        }
    };
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            if (!st[i][j] && g[i][j] == '#')
            {
                uid++;
                dfs(dfs, i, j, uid);
            }
            if (g[i][j] == '.')
            {
                cnt++;
            }
        }
    }
    ll ans = 0;
    cnt = qmi(cnt, mod - 2) % mod;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            if (g[i][j] == '.')
            {
                map<int, bool> mp;
                for (int k = 0; k < 4; k++)
                {
                    int a = i + dx[k];
                    int b = j + dy[k];
                    // cout << a << ' ' << b << endl;
                    if (a >= 1 && b >= 1 && a <= n && b <= m && g[a][b] == '#')
                    {
                        // cout << id[a][b] << endl;
                        if (!mp.count(id[a][b]))
                        {
                            mp[id[a][b]] = true;
                        }
                    }
                }
                ll t = uid - mp.size() + 1;
                ans = ((ans + (t * cnt) % mod + mod) % mod + mod) % mod;
            }
        }
    }
    cout << ans << endl;
}

signed main()
{
    int t = 1;
    while (t--)
    {
        solve();
    }
    return 0;
}

F - Christmas Present 2

解题思路:

\(dp[i]:考虑前i个位置的最小总距离。\)

\(dist[i]:从礼物屋子到第i个房子的直线距离\)

\(d[i][j]:从第i个屋子到大第j个屋子的直线距离\)

\(pre[i]:从第1个屋子到第i个屋子的顺序总距离\)

\[\begin{align*} dp[i] &= min\{dp[j] + dist[j + 1] + \sum_{k = j + 1}^{i - 1}d[k][k + 1] + dist[i]\} \\ &= min\{dp[j] + dist[j + 1] + (pre[i] - pre[j + 1]) + dist[i]\} \\\\ &= dist[i] + pre[i] + min\{(dp[j] + dist[j + 1] - pre[j + 1])\} \end{align*} \]

我们设定:

\[f[j] = dp[j] + dist[j + 1] - pre[j + 1] \]

\[dp[i] =dist[i] + pre[i] + min\{f[j]\} \]

对于上述式子有

\[j \in [max(0,i - k) ,i - 1] \]

\[dp[i] = 在j点结束后 +从起点到(j + 1)点+从(j+1)顺序走到i点 + 从i点回到礼物屋 \]

枚举所有范围内的\(j\)得到最小值就是\(dp[i]\)的最终答案。

动态维护长度为\(k\)的区间中的最小值,我们可用滑动窗口\(O(n)\)完成。

当然,本题用其他动态查询区间最值的数据结构也可在\(O(nlogn)\)通过。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 310;
typedef pair<ll, ll> pii;
typedef pair<pii, ll> piii;
#define fi first
#define se second
const int mod = 998244353;

void solve()
{
    int n, k;
    cin >> n >> k;
    vector<pii> p(n + 1);
    for (int i = 0; i <= n; i++)
    {
        cin >> p[i].fi >> p[i].se;
    }
    vector<double> pre(n + 1), dist(n + 1);
    auto getd = [&](ll x1, ll y1, ll x2, ll y2) -> double
    {
        return sqrtl((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
    };
    for (int i = 1; i <= n; i++)
    {
        dist[i] = getd(p[0].fi, p[0].se, p[i].fi, p[i].se);
        if (i > 1)
        {
            pre[i] = getd(p[i].fi, p[i].se, p[i - 1].fi, p[i - 1].se);
        }
    }
    for (int i = 2; i <= n; i++)
    {
        pre[i] += pre[i - 1];
    }
    vector<double> dp(n + 1), f(n + 1);
    deque<int> q;
    q.push_back(0);
    f[0] = dp[0] + dist[1] - pre[1];
    // cout << dp[0] << ' ' << dist[1] << endl;
    for (int i = 1; i <= n; i++)
    {
        if (q.size() && q.front() < i - k)
        {
            q.pop_front();
        }
        dp[i] = pre[i] + dist[i] + f[q.front()];
        f[i] = dp[i] + dist[i + 1] - pre[i + 1];
        // cout << i << ' ' << q.front() << endl;
        while (q.size() && f[q.back()] >= f[i])
        {
            q.pop_back();
        }
        q.push_back(i);
    }
    // cout << pre[3] << endl;
    printf("%.20lf", dp[n]);
}

int main()
{
    int t = 1;
    while (t--)
    {
        solve();
    }
    return 0;
}