AtCoder Beginner Contest 326

这篇具有很好参考价值的文章主要介绍了AtCoder Beginner Contest 326。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

A - 2UP3DOWN (abc326 A)

题目大意

100楼层,一次可以上最多两层,或下最多三层。

给定两楼层,问能否一次到达。

解题思路

比较大小,然后判断其差是是不是在\(2\)\(3\)内即可。

神奇的代码
#include <bits/stdc++.h>
using namespace std;
using LL = long long;

int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int x, y;
    cin >> x >> y;
    if (x > y && x - y <= 3)
        cout << "Yes" << '\n';
    else if (x <= y && y - x <= 2)
        cout << "Yes" << '\n';
    else
        cout << "No" << '\n';

    return 0;
}



B - 326-like Numbers (abc326 B)

题目大意

给定一个\(n\),问不小于 \(n\)的形如 \(326\)的数字是多少。

形如 \(326\)的数字,即数位有 \(3\),且百位 \(\times\)十位 \(=\)个位。

解题思路

只有\(1000\)个数,枚举判断即可。

神奇的代码
#include <bits/stdc++.h>
using namespace std;
using LL = long long;

int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n;
    cin >> n;
    auto is_326 = [](int x) {
        auto s = to_string(x);
        return (s[0] - '0') * (s[1] - '0') == (s[2] - '0');
    };
    while (!is_326(n))
        ++n;
    cout << n << '\n';

    return 0;
}



C - Peak (abc326 C)

题目大意

给定一维数轴上的\(n\)个礼物点,问长度为\(M\)的左闭右开的区间最多有多少个点。

解题思路

注意到最好情况下,其区间的左端点一定是礼物点。

因此我们可以枚举左端点所在的礼物点,然后看看到右端点时包含了多少个礼物。这个可以先对礼物点排序然后二分找到右端点礼物,作差得到数量。

当然也可以双指针。

ranges::的用法是c++20的特性。

神奇的代码
#include <bits/stdc++.h>
using namespace std;
using LL = long long;

int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n, m;
    cin >> n >> m;
    vector<int> a(n);
    for (auto& i : a)
        cin >> i;
    ranges::sort(a);
    int ans = 0;
    for (int i = 0; i < n; ++i) {
        ans = max(ans, int(ranges::lower_bound(a, a[i] + m) - a.begin() - i));
    }
    cout << ans << '\n';

    return 0;
}



D - ABC Puzzle (abc326 D)

题目大意

给定两个仅包含ABC的长度为\(n\)的串\(a,b\),要求构造一个\(n \times n\)的矩阵,要求:

  • 每行每列包含恰好一个ABC
  • 每行最左边的字母组成字符串\(a\)
  • 每列最顶部的字母组成字符串\(a\)

解题思路

因为\(n\)只有 \(5\),考虑朴素搜索。

每行ABC的排列情况只有\(5 \times 4 \times 3 = 60\)种, \(5\)行的总情况为 \(60^5 = 7e9\),但如果中间剪枝的话其合法情况数远远小于该数。

具体来说,考虑当前位置 \((x,y)\)放什么,我们需要第 \(x\)行的放置情况 \(row[x]\),第 \(y\)列的放置情况 \(col[y]\),以决定该位置能否放该字母(代码里是二进制压缩的状态)。还需要 \(left[x]\)表示第 \(x\)行的是否放过字母,以决定是否和字符串 \(a\)比较,同理也需要 \(top[y]\)表示第 \(y\)列是否放过字母,以决定是否和字符串 \(b\)比较。这里的剪枝可以减去大部份合法情况。

在考虑完一行后,可以看看 \(row[x]\)是否放了ABC三个字母,没放满则直接剪枝。

感觉写的很复杂。

神奇的代码
#include <bits/stdc++.h>
using namespace std;
using LL = long long;

int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n;
    string a, b;
    cin >> n >> a >> b;
    vector<vector<int>> ans(n, vector<int>(n, -1));
    vector<int> top(n, 1);
    vector<int> left(n, 1);
    vector<int> row(n);
    vector<int> col(n);
    auto not_have = [&](int x, int y) { return ((~x >> y) & 1); };
    function<bool(int, int)> dfs = [&](int x, int y) {
        if (x == n) {
            for (auto& i : row)
                if (i != 7)
                    return false;
            for (auto& i : col)
                if (i != 7)
                    return false;
            return true;
        }

        for (int i = 0; i < 3; ++i) {
            if (not_have(row[x], i) && not_have(col[y], i)) {
                if (top[y] && b[y] - 'A' != i)
                    continue;
                if (left[x] && a[x] - 'A' != i)
                    continue;
                row[x] |= (1 << i);
                col[y] |= (1 << i);
                ans[x][y] = i;

                int ttop = top[y], lleft = left[x];
                top[y] = 0;
                left[x] = 0;
                if (y == n - 1) {
                    if (row[x] == 7 && dfs(x + 1, 0))
                        return true;
                } else {
                    if (dfs(x, y + 1))
                        return true;
                }
                row[x] ^= (1 << i);
                col[y] ^= (1 << i);
                ans[x][y] = -1;
                top[y] = ttop;
                left[x] = lleft;
            }
        }

        if (y == n - 1) {
            if (row[x] != 7)
                return false;

            if (dfs(x + 1, 0))
                return true;
        } else {
            if (dfs(x, y + 1))
                return true;
        }

        return false;
    };
    if (dfs(0, 0)) {
        cout << "Yes" << '\n';
        for (auto& i : ans) {
            for (auto& j : i) {
                if (j == -1)
                    cout << '.';
                else
                    cout << char(j + 'A');
            }
            cout << '\n';
        }
    } else
        cout << "No" << '\n';

    return 0;
}



E - Revenge of "The Salary of AtCoder Inc." (abc326 E)

题目大意

给定包含\(n\)个数字的数组 \(a\),以及一个等概率的 \(n\)面骰子。进行以下游戏:

初始\(x=0\),投掷一次骰子,得到 \(y\)

  • 如果\(x < y\),则获得 \(a_y\)元,同时令 \(x=y\)
  • 否则游戏结束

问期望获得的钱数。

解题思路

期望题,根据定义,一个状态的期望,它是所有后继状态的期望的加权平均,这里的权重是概率。

当前状态是\(x\),则设\(dp[x]\)表示当前掷出的值为 \(x\),继续游戏至游戏结束,这期间获得的期望钱数。

很显然初始条件 \(dp[n] = 0\),即 \(x=n\)时,无论怎么骰,始终有 \(y \leq n\),游戏总是会结束。

考虑一般情况,当前状态是\(x\),考虑投掷一次骰子的后继状态:

  • \(\frac{x}{n}\)的概率投掷出\(y \leq x\),此时游戏结束,后继状态的期望收入为 \(0\)
  • \(\frac{1}{n}\)的概率投掷出\(y = x + 1\),此时进入后继状态\(dp[x+1]\),获得收益\(a_{x+1}\)
  • \(\frac{1}{n}\)的概率投掷出\(y = x + 2\),此时进入后继状态\(dp[x+2]\),获得收益\(a_{x+2}\)
  • \(\frac{1}{n}\)的概率投掷出\(y = x + 3\),此时进入后继状态\(dp[x+3]\),获得收益\(a_{x+3}\)
  • ...
  • \(\frac{1}{n}\)的概率投掷出\(y = n\),此时进入后继状态\(dp[n]\),获得收益\(a_{n}\)

由此可以写出转移式子:

\[dp[x] = \frac{x}{n} \times 0 + \sum_{i=x+1}^{n}\frac{1}{n} (dp[i] + a[i]) = \frac{1}{n}\sum_{i=x+1}^{n}(dp[i] + a[i]) \]

这是一个后缀和,求\(dp\)的时候维护一下就可以了。观察到\(dp\)数组和后缀和的关系,代码里直接把\(dp\)数组省掉了。

神奇的代码
#include <bits/stdc++.h>
using namespace std;
using LL = long long;

const int mo = 998244353;

long long qpower(long long a, long long b) {
    long long qwq = 1;
    while (b) {
        if (b & 1)
            qwq = qwq * a % mo;
        a = a * a % mo;
        b >>= 1;
    }
    return qwq;
}

long long inv(long long x) { return qpower(x, mo - 2); }

int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n;
    cin >> n;
    vector<int> a(n);
    for (auto& i : a)
        cin >> i;
    int presum = 0, invn = inv(n);
    for (int i = n - 1; i >= 0; --i) {
        presum = (0ll + presum + 1ll * presum * invn % mo + a[i]) % mo;
    }
    cout << 1ll * presum * invn % mo << '\n';

    return 0;
}



F - Robot Rotation (abc326 F)

题目大意

二维平面,机器人初始 \((0,0)\),面向\(x\)轴正方向。给定\(n\)次移动的距离数组\(d\),每次移动前,你需要指定机器人顺时针或逆时针转 \(90\)度,随后移动。

问能否移动到达目标点 \((x,y)\),能移动到则给出一个可行的旋转序列。

解题思路

注意到\(n\)只有\(80\),且每次必须旋转机器人,这意味着机器人有一半是上下移动,一半是左右移动,最多 \(40\)次。

横纵坐标的移动我们是可以分开考虑的,因此我们就分别考虑横坐标移动的 \(40\)次操作和纵坐标移动的 \(40\)次操作。

而操作,事实上就是决定移动距离的正负性。注意到 \(40\)其实是个很微妙的性质,它的一半 \(20\)是可以承受指数的复杂度的。即采用折半搜索的策略。

即对于这 \(40\)次操作,我们要对它们赋予正负号,看它们的和能否成为 目标移动距离\(x\)(或 \(y\))。

我们可以分别对前\(20\)个数和后\(20个数\),花 \(O(2^{20})\)枚举它们的正负号,记录它们的和。

然后再把这两部份的结果合并:能否从左右两边的结果各挑一个数,它们的和\(=x\)。这是一个非常简单的子问题,对两边排序后一个双指针就可以解决了。这里的时间复杂度是 \(O(2^{20} \log)\)

分别对\(x,y\)方向进行一次折半搜索,就可以搜到结果了。

由于要输出方案,因此我们得记录该结果的每一项的正负号,下面代码是通过二进制压缩的形式记录的,最后还要通过每一项的正负号,以及当前机器人的朝向决定向左向右转。

神奇的代码
#include <bits/stdc++.h>
using namespace std;
using LL = long long;

int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n, x, y;
    cin >> n >> x >> y;
    array<vector<int>, 2> a;
    for (int i = 0; i < n; ++i) {
        int x;
        cin >> x;
        a[i & 1].push_back(x);
    }
    auto dfs = [&](auto self, const vector<int>& a, int pos, int sum, int sol,
                   int l, int r, vector<array<int, 2>>& tmp) {
        if (pos + l == r) {
            tmp.push_back({sum, sol});
            return;
        }
        self(self, a, pos + 1, sum + a[pos + l], sol, l, r, tmp);
        self(self, a, pos + 1, sum - a[pos + l], (sol | (1 << pos)), l, r, tmp);
    };
    auto solve = [&](const vector<int>& a, int val) {
        int mid = a.size() / 2;
        vector<array<int, 2>> l, r;
        dfs(dfs, a, 0, 0, 0, 0, mid, l);
        dfs(dfs, a, 0, 0, 0, mid, a.size(), r);
        vector<int> lid(l.size()), rid(r.size());
        iota(lid.begin(), lid.end(), 0);
        iota(rid.begin(), rid.end(), 0);
        ranges::sort(lid, [&](int x, int y) { return l[x][0] < l[y][0]; });
        ranges::sort(rid, [&](int x, int y) { return r[x][0] > r[y][0]; });
        auto lp = lid.begin(), rp = rid.begin();
        while (lp != lid.end() && rp != rid.end()) {
            if (l[*lp][0] + r[*rp][0] == val) {
                return l[*lp][1] + ((1ll * r[*rp][1]) << mid);
            } else if (l[*lp][0] + r[*rp][0] < val) {
                lp = next(lp);
            } else if (l[*lp][0] + r[*rp][0] > val) {
                rp = next(rp);
            }
        }
        return -1ll;
    };
    auto dy = solve(a[0], y); // 0 => +, 1 => -
    auto dx = solve(a[1], x);
    if (dy == -1 || dx == -1)
        cout << "No" << '\n';
    else {
        cout << "Yes" << '\n';
        vector<int> ans;
        for (int i = 0; i <= n / 2; ++i) {
            ans.push_back((dy >> i) & 1);
            if (i < n / 2)
                ans.push_back((dx >> i) & 1);
        }
        int dir = 0;
        for (int i = 0; i < n; ++i) {
            cout << "LR"[ans[i] ^ dir ^ (i & 1)];
            dir = ans[i];
        }
        cout << '\n';

    }

    return 0;
}



G - Unlock Achievement (abc326 G)

题目大意

给定\(n\)个技能和 \(m\)个成就。对于第 \(i\)个技能,升一级花费 \(c_i\)

达成第 \(i\)个成就, 有\(a_i\)的奖励,达成条件为,对于每个技能要达到指定等级或以上。

问最大的收益,即奖励\(-\)花费的最大值。

解题思路

考虑只有一个技能和一个成就,那我们选择是否完成这个成就,就看其技能升级的成本成就的奖励的大小。

当考虑多个一个技能和多个成就时,成本奖励之间的衡量就没那么单纯:我可能完成了一个成就,而当我升级一次技能,又能立刻完成另一个成就——即不用从零等级技能考虑。这种有泛泛的,复杂关系决策的,网络流可能会比较在行。

成就只有达成未达成两种状态,而技能有5种状态,但如果根据完成成就的条件——某技能等级于x或以上,将技能拆分成这\(5\)种情况,那么这些情况同样也只有 达成未达成两种状态。

接下来要做的就是规定每个成就和每个技能状态,是达成不达成,其中会有一些代价,这种二分类问题的最小化代价,可以转换成最小割问题。而最小割的问题可以转换成最大流求解。

考虑一张图,有源点\(S\)和汇点\(T\),其余点就是上述所说的状态,即每个成就表示成一个点,每个技能拆分成5个点,分别表示该技能等级达到i级或以上

一个会将这张图分成两部分,一部分与\(S\)相连,一部分与\(T\)相连。可以规定与\(S\)相连的点表示状态 未达成,与\(T\)相连的点表示达成

由于最小割是最小化代价,而成就奖励要最大化,这里需要转换一下,先假设完成了所有成就,那我们的决策就是决定成就是否不完成,即最小化未达成成就的代价

考虑如何连边以及边权(容量)设定,注意到网络流里,当一条边的容量满了,意味着这条边被割去了,即不与\(S\)(或 \(T\))相连,换句话说边权就是不成为某一类的代价

对于成就这一状态,它不成为达成状态的代价就是a_i,即如果我选择不达成该成就,即与\(T\)的边断开,则我将失去其奖励 \(a_i\)。因此每个成就与汇点\(T\)连一条容量为 \(a_i\)的边。

对于 技能,它有5个状态,(以下等级1表示技能等级达到1或以上)除了等级1状态外,源点\(S\)与其他状态 连一条容量为\(c_i\)的边,即升级一次的代价。比如 等级2状态,我花费\(c_i\)升级一次至等级 \(2\),那该状态就是 达成的,它不成为未达成这一状态了。

当然这里需要避免一种情况,就是等级3达成了,但等级2未达成。我们需要从等级2连一条边到等级3,其容量为无穷大。这样子,尽管\(S \to 3 \to ... \to T\)的边割去了,还存在 \(S \to 2 \to 3 \to ... \to T\) 的路径,要割去这条路径,只能把\(S \to 2\)也割去,这样子 等级2也达成了。因为\(2 \to 3\)是无穷大的,所以这条边不会被割去,它只能割\(S \to 2\),因为其代价更小。这意味着技能等级之间的依赖关系不能被割去。

还有一种避免的情况就是,成就要求的技能等级都达成了,但成就未达成,这需要连一条从对应的技能状态该成就的容量为 无穷大的边,这意味着技能和成就之间的关系不能被割去。

建好图后,跑一遍最大流得最小割,用成就总奖励减去最小割即为答案。文章来源地址https://www.toymoban.com/news/detail-711401.html

神奇的代码
#include <bits/stdc++.h>
using namespace std;
using LL = long long;

template <typename T> class flow_graph {
  public:
    static constexpr T eps = (T)1e-9;

    struct edge {
        int from;
        int to;
        T c;
        T f;
    };

    vector<vector<int>> g;
    vector<edge> edges;
    int n;
    int st;
    int fin;
    T flow;

    flow_graph(int _n, int _st, int _fin) : n(_n), st(_st), fin(_fin) {
        assert(0 <= st && st < n && 0 <= fin && fin < n && st != fin);
        g.resize(n);
        flow = 0;
    }

    void clear_flow() {
        for (const edge& e : edges) {
            e.f = 0;
        }
        flow = 0;
    }

    int add(int from, int to, T forward_cap, T backward_cap) {
        assert(0 <= from && from < n && 0 <= to && to < n);
        int id = (int)edges.size();
        g[from].push_back(id);
        edges.push_back({from, to, forward_cap, 0});
        g[to].push_back(id + 1);
        edges.push_back({to, from, backward_cap, 0});
        return id;
    }
};

template <typename T> class dinic {
  public:
    flow_graph<T>& g;

    vector<int> ptr;
    vector<int> d;
    vector<int> q;

    dinic(flow_graph<T>& _g) : g(_g) {
        ptr.resize(g.n);
        d.resize(g.n);
        q.resize(g.n);
    }

    bool expath() {
        fill(d.begin(), d.end(), -1);
        q[0] = g.fin;
        d[g.fin] = 0;
        int beg = 0, end = 1;
        while (beg < end) {
            int i = q[beg++];
            for (int id : g.g[i]) {
                const auto& e = g.edges[id];
                const auto& back = g.edges[id ^ 1];
                if (back.c - back.f > g.eps && d[e.to] == -1) {
                    d[e.to] = d[i] + 1;
                    if (e.to == g.st) {
                        return true;
                    }
                    q[end++] = e.to;
                }
            }
        }
        return false;
    }

    T dfs(int v, T w) {
        if (v == g.fin) {
            return w;
        }
        int& j = ptr[v];
        while (j >= 0) {
            int id = g.g[v][j];
            const auto& e = g.edges[id];
            if (e.c - e.f > g.eps && d[e.to] == d[v] - 1) {
                T t = dfs(e.to, min(e.c - e.f, w));
                if (t > g.eps) {
                    g.edges[id].f += t;
                    g.edges[id ^ 1].f -= t;
                    return t;
                }
            }
            j--;
        }
        return 0;
    }

    T max_flow() {
        while (expath()) {
            for (int i = 0; i < g.n; i++) {
                ptr[i] = (int)g.g[i].size() - 1;
            }
            T big_add = 0;
            while (true) {
                T add = dfs(g.st, numeric_limits<T>::max());
                if (add <= g.eps) {
                    break;
                }
                big_add += add;
            }
            if (big_add <= g.eps) {
                break;
            }
            g.flow += big_add;
        }
        return g.flow;
    }

    vector<int> min_cut() {
        max_flow();
        vector<int> ret(g.n);
        for (int i = 0; i < g.n; i++) {
            ret[i] = (d[i] != -1);
        }
        return ret;
    }
};

const int inf = 1e9 + 7;

int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n, m;
    cin >> n >> m;
    vector<int> c(n), a(m);
    for (auto& i : c)
        cin >> i;
    for (auto& i : a)
        cin >> i;
    int st = 0, pst = st + 1, ast = pst + n * 5, ed = ast + m, num = ed + 1;
    flow_graph<int> g(num, st, ed);
    for (int i = 0; i < n; ++i) {
        int l = i * 5, r = l + 5;
        for (int j = l; j < r; ++j) {
            int pj = pst + j;
            if (j == l) {
                g.add(pj, ed, inf, 0);
            } else {
                g.add(st, pj, c[i], 0);
                g.add(pj - 1, pj, inf, 0);
            }
        }
    }
    for (int i = 0; i < m; ++i) {
        int ai = ast + i;
        g.add(ai, ed, a[i], 0);
    }
    for (int i = 0; i < m; ++i)
        for (int j = 0; j < n; ++j) {
            int x;
            cin >> x;
            --x;
            int ai = ast + i, pj = pst + j * 5 + x;
            g.add(pj, ai, inf, 0);
        }
    dinic solver(g);
    int ans = accumulate(a.begin(), a.end(), 0) - solver.max_flow();
    cout << ans << '\n';

    return 0;
}



到了这里,关于AtCoder Beginner Contest 326的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • AtCoder Beginner Contest 311

    给定一个字符串,问最短的一个前缀,包含 A B C 这三个字符。 注意到这个前缀的末尾字母一定是这三个字母中的一个,因此答案就是这三个字母出现位置最早的最大值。 神奇的代码 给定 (n) 个人的 (d) 天的空闲与否的情况,问最长的连续天,这 (n) 个人都空闲。 我们找

    2024年02月16日
    浏览(33)
  • AtCoder Beginner Contest 318

    咕咕咕,总力战还没打,凹不过卷狗,躺了.jpg 给定 (n, m, p) ,问有多少个 (i) 满足 (0 m+pi leq n) 减去初始的 (m) ,剩下的就是看 (p) 的倍数个数。 神奇的代码 一个二维空间,有 (n) 个矩形覆盖。 问有多大的空间被覆盖了。重复覆盖算一次。 空间大小只有 (100) ,矩形

    2024年02月10日
    浏览(30)
  • AtCoder Beginner Contest 328

    给定 (n) 个数字和一个数 (x) 。 问不大于 (x) 的数的和。 按找要求累计符合条件的数的和即可。 神奇的代码 给定一年的月数和一个月的天数。 问有多少对 ((i,j)) ,表示第 (i) 个月的第 (j) 日, (i,j) 的数位上每个数字都是一样的。 范围只有 (O(100^2)) ,枚举所有的

    2024年02月05日
    浏览(27)
  • AtCoder Beginner Contest 323

    有的人边上课边打abc 给定一个 (01) 字符串,问偶数位(从 (1) 开始) 是否全为 (0) 。 遍历判断即可。 神奇的代码 给定 (n) 个人与其他所有人的胜负情况。问最后谁赢。 一个人获胜次数最多则赢,若次数相同,则编号小的赢。 统计每个人的获胜次数,排个序即可。 神奇

    2024年02月08日
    浏览(22)
  • AtCoder Beginner Contest 299

    给定一个包含 |*. 的字符串,其中 | 两个, * 一个,问 * 是否在两个 | 之间。 找到两个 | 的下标 (l, r) 以及 * 的下标 (mid) ,看看是否满足 (l mid r) 即可。 神奇的代码 给定 (n) 个人的卡片,颜色为 (c_i) ,数字为 (r_i) 。 如果其中有颜色为 (T) 的牌,则该颜色中数字最大

    2023年04月23日
    浏览(15)
  • AtCoder Beginner Contest 324

    在高铁上加训! 给定 (n) 个数,问是否都相等。 判断是不是全部数属于第一个数即可。或者直接拿 set 去重。 神奇的代码 给定一个数 (N) ,问是否能表示成 (2^x3^y) 。 指数范围不会超过 (64) ,花 (O(64^2)) 枚举判断即可。 神奇的代码 给定一个字符串 (t) 和若干个字符串

    2024年02月08日
    浏览(28)
  • AtCoder Beginner Contest 348

    给定 (n) ,输出 (ooxooxoox...) ,长度为 (n) 。 按题意模拟即可。 神奇的代码 给定 (n) 个点,对每个点,求出与其距离最远的点的下标。 (n) 只有 (100) ,对于每个点,花 (O(n)) 遍历每个点最大化距离,时间复杂度为 (O(n^2)) 。 神奇的代码 (n) 个豌豆,每个豌豆有美味值

    2024年04月08日
    浏览(33)
  • AtCoder Beginner Contest 325

    感觉错失了上分机会 给定姓和名,输出尊称,即姓+ san 。 按照题意模拟即可。 神奇的代码 给定 (n) 个地区的公司人数和对应的时区,规定上班时间为 (9:00-18:00) ,现召开一小时会议,上班期间的公司可以参加。问订个时间,能参与的人数的最大值。 枚举开会的时间,然后

    2024年02月08日
    浏览(23)
  • AtCoder Beginner Contest 330

    给定 (n) 个学生的分数,以及及格分 (x) ,问多少人及格了。 依次判断即可。 神奇的代码 回答 (n) 个问题,每个问题给定 (a,l,r) ,问函数 (f(x) = |x - a|) 在 ([l,r]) 的最小值。 全定义域下,最小值显然在 (x=a) 取得。绝对值函数图像是 (V) 型。 现在限定在 ([l,r]) ,则

    2024年02月05日
    浏览(108)
  • AtCoder Beginner Contest 332

    坐地铁时口糊了6题,回来写时结果爆 long long , 0 没有逆元,卡了好久 线上购物,买了 (n) 种物品,分别给出它们的单价和数量。 若总价少于 (s) 元,则需要支付 (k) 元邮费,否则包邮。 问总价多少。 求个和判断下是否加邮费即可。 神奇的代码 一个容量为 (G) 的玻璃杯

    2024年02月04日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包