UNIQUE VISION Programming Contest 2023 Autumn(AtCoder Beginner Contest 323)

发布时间 2023-10-08 12:18:18作者: value0

UNIQUE VISION Programming Contest 2023 Autumn(AtCoder Beginner Contest 323)

A. Weak Beats

解题思路:

按题意模拟即可。

代码:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

void solve()
{
    string s;
    cin >> s;
    int n = s.size();
    for (int i = 0; i < n; i++)
    {
        if (i & 1)
        {
            if (s[i] == '1')
            {
                puts("No");
                return;
            }
        }
    }
    puts("Yes");
}

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

B. Round-Robin Tournament

解题思路:

暴力统计每一行有多少个\(o\),然后排个序即可。

代码:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
#define fi first
#define se second
bool cmp(pii a, pii b)
{
    if (a.fi != b.fi)
    {
        return a.fi > b.fi;
    }
    return a.se < b.se;
}
void solve()
{
    int n;
    cin >> n;
    vector<pii> cnt(n);
    for (int i = 0; i < n; i++)
    {
        string s;
        cin >> s;
        cnt[i].se = i;
        for (auto c : s)
        {
            if (c == 'o')
            {
                cnt[i].first++;
            }
        }
    }
    sort(cnt.begin(), cnt.end(), cmp);
    for (auto v : cnt)
    {
        cout << v.se + 1 << ' ';
    }
}

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

C. World Tour Finals

解题思路:

从大到小枚举每个玩家的分数,从大到小枚举每到题的分数,如果没选过就选上,一旦大于了最大值,新加的题数就是答案。

代码:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
#define fi first
#define se second

void solve()
{
    int n, m;
    cin >> n >> m;
    vector<int> a(m + 1);
    vector<pii> b(m + 1);
    for (int i = 1; i <= m; i++)
    {
        cin >> a[i];
        b[i].fi = a[i];
        b[i].se = i;
    }
    vector<pii> p(n + 1);
    vector<vector<bool>> st(n + 1, vector<bool>(m + 1));
    for (int i = 1; i <= n; i++)
    {
        p[i].fi += i;
        p[i].se = i;
        string s;
        cin >> s;
        s = ' ' + s;
        for (int j = 1; j <= m; j++)
        {
            if (s[j] == 'o')
            {
                st[i][j] = true;
                p[i].fi += a[j];
            }
        }
    }
    sort(p.begin() + 1, p.end());
    sort(b.begin() + 1, b.end());
    vector<int> ans(n + 1);

    for (int i = n; i; i--)
    {
        int cnt = 0;
        int cur = 0;
        if (i == n)
        {
            if (p[n - 1].fi == p[i].fi)
            {
                cur = p[i].fi;
            }
            else
            {
                continue;
            }
        }
        else
        {
            cur = p[i].fi;
        }
        for (int j = m; j; j--)
        {
            if (!st[p[i].se][b[j].se])
            {
                cur += b[j].fi;
                cnt++;
                if (cur > p[n].fi)
                {
                    ans[p[i].se] = cnt;
                    break;
                }
            }
        }
    }
    for (int i = 1; i <= n; i++)
    {
        // cout << p[i].fi << ' ' << p[i].se << endl;
        cout << ans[i] << endl;
    }
}

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

D. Merge Slimes

解题思路:

从小到大看,能合并就合并。合并得到的继续能合并就合并。

每次合并剩余的不能合并的(就是只剩一个的),记得累加。

代码:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
#define fi first
#define se second

void solve()
{
    int n;
    cin >> n;
    map<ll, ll> v;
    for (int i = 1; i <= n; i++)
    {
        int a, b;
        cin >> a >> b;
        v[a] = b;
    }
    for (auto &a : v)
    {
        ll cur = 1;
        ll res = a.se >> 1;
        a.se = a.se % 2;
        ll t = a.fi;
        while (res)
        {
            cur = res >> 1;
            t <<= 1;
            if (v.count(t))
            {
                v[t] += (res % 2);
            }
            else
            {
                v[t] = (res % 2);
            }
            res >>= 1;
        }
    }
    ll ans = 0;
    for (auto a : v)
    {
        // cout << a.fi << ' ' << a.se << endl;
        ans += a.se;
    }
    cout << ans;
}

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

E. Playlist

解题思路:

\(f[i]\):如\(X\)\(i\),答案为多少。

\(f[0]\)第一步只能选第一首歌,所以答案就是\(\frac{1}{n}\)

对于每一个\(i\),遍历所有的歌。

对于第\(j\)首歌:

  • \(t[j] > i\),那么情况等同于\(f[0]\),即我们选了这首歌,\(X +0.5\)放的就是这首。所以如果\(j == 1,f[i] = f[i] + \frac{1}{n}\)
  • \(t[j] \leq i\),那么情况等同于\(f[i-t[j]]\)\(f[i - t[j]]\)相当于时间\(0 \rightarrow (i - t[j])\),就是要求选歌使得第\((i - t[j])+0.5\)秒后放的是第一首歌。\(f[i]\)可以相当于时间\(t[j] \rightarrow i\),同样要求选歌使得第\((i - t[j])+0.5\)秒后放的是第一首歌。二者问题等价。

时间复杂度:\(O(nx)\)

代码:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
#define fi first
#define se second
const int mod = 998244353;
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, x;
    cin >> n >> x;
    vector<int> t(n + 1);
    for (int i = 1; i <= n; i++)
    {
        cin >> t[i];
    }
    // f[i]:X为i时的可能性
    vector<ll> f(x + 10);
    // X为0时,第一步就要选到第一首歌,所以答案是1/n
    f[0] = qmi(n, mod - 2);
    // X为i时,如果要X+0.5秒的时候正好在放第1首歌。
    // 如果t[j] > i,意味着我们第一首歌如果点j,那么X + 0.5时播放的就是第j首,这和X等于0等价
    // 所以若此时j == 1,那么答案加上1 / n。
    // 如果t[j] <= i,意味着我们可以从f[i - t[j]]转移过来。
    // 从i - t[j] 到 i 和 从 0 到 i 是等价的。所以此时f[i] += f[i - t[j]].
    // 由于从每个(i - t[j])转移过来的情况是独立的,所以就可以变成加法了。
    ll inv = qmi(n, mod - 2);
    for (int i = 1; i <= x; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            if (t[j] > i)
            {
                f[i] = (f[i] + (j == 1) * inv) % mod;
            }
            else
            {
                f[i] = (f[i] + f[i - t[j]] * inv) % mod;
            }
        }
    }
    cout << f[x];
}

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