AtCoder Beginner Contest 340

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

A - Arithmetic Progression (abc340 A)

题目大意

给定等差数列的首项末项公差

输出这个等差数列。

解题思路

首相依次累加公差末项即可。

神奇的代码
#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 a, b, d;
    cin >> a >> b >> d;
    while (a <= b) {
        cout << a << ' ';
        a += d;
    }
    cout << '\n';

    return 0;
}



B - Append (abc340 B)

题目大意

依次进行\(Q\)次操作,分两种。

  • 1 x,将x放到数组\(a\)的末尾。
  • 2 k,输出数组\(a\)的倒数第 \(k\)项。

解题思路

vector模拟即可,操作2可快速寻址访问。

神奇的代码
#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 q;
    cin >> q;
    vector<int> a;
    while (q--) {
        int op;
        cin >> op;
        if (op == 1) {
            int x;
            cin >> x;
            a.push_back(x);
        } else {
            int k;
            cin >> k;
            cout << a[a.size() - k] << '\n';
        }
    }

    return 0;
}



C - Divide and Divide (abc340 C)

题目大意

黑板一个数\(x\),依次进行以下操作,直到黑板上的数全是\(1\)

  • \(x\)擦去,写上 \(\lfloor x \rfloor\)\(\lceil x \rceil\),耗费 \(x\)精力。

问最后耗费精力的和。

解题思路

朴素做法就一个简单的队列模拟即可。

但这会超时,因为对于同一个数可能会出现多次,而上述做法会对每个数都进行一次操作,这样之后的数的个数是指数增长的。

如何优化呢?那就是对于出现多次的同一个数,我们一次全部做完。

即记录\(cnt[x]\)表示黑板上 \(x\) 的出现次数,然后我们分解它,\(cnt[\lfloor x \rfloor] += cnt[x], cnt[\lceil x \rceil] += cnt[x]\)。为了不重复分解,每次取最大的数进行分解即可。

感觉上这样分解的次数不会超过 \(O(\log)\)或者 \(O(\log^2)\) 次。

神奇的代码
#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);
    LL n;
    cin >> n;
    set<LL> team;
    map<LL, LL> cnt;
    cnt[n] = 1;
    team.insert(n);
    LL ans = 0;
    while (!team.empty()) {
        LL u = *team.rbegin();
        if (u == 1)
            break;
        team.erase(u);
        if (cnt[u] > 0) {
            ans += u * cnt[u];
            team.insert(u / 2);
            cnt[u / 2] += cnt[u];
            team.insert(u - u / 2);
            cnt[u - u / 2] += cnt[u];
            cnt[u] = 0;
        }
    }
    cout << ans << '\n';

    return 0;
}




D - Super Takahashi Bros. (abc340 D)

题目大意

\(n\)个关卡,初始只能打第一关卡。

对于第 \(i\)关卡,可以花 \(a_i\)代价解锁第 \(i+1\)关卡,或花 \(b_i\)代价解锁第 \(x_i\)关卡。

问解锁第 \(n\)关卡的最小代价。

解题思路

虽然说是解锁,但很显然打的下一关肯定是刚刚解锁的关卡。

根据上述解锁关系建一张图,边权就是解锁代价,原问题就是问点\(1\)到点 \(n\)的最短距离,跑一遍 dijkstra即可。

神奇的代码
#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;
    vector<vector<array<int, 2>>> edge(n);
    for (int i = 0; i < n - 1; ++i) {
        int a, b, d;
        cin >> a >> b >> d;
        --d;
        edge[i].push_back({i + 1, a});
        edge[i].push_back({d, b});
    }
    priority_queue<array<LL, 2>, vector<array<LL, 2>>, greater<array<LL, 2>>>
        pq;
    vector<LL> dis(n, 1e18);
    dis[0] = 0;
    pq.push({0, 0});
    while (!pq.empty()) {
        auto [d, u] = pq.top();
        pq.pop();
        if (d > dis[u])
            continue;
        for (auto [v, w] : edge[u]) {
            if (dis[v] > dis[u] + w) {
                dis[v] = dis[u] + w;
                pq.push({dis[v], v});
            }
        }
    }
    cout << dis[n - 1] << endl;

    return 0;
}



E - Mancala 2 (abc340 E)

题目大意

\(n\)个盒子,第 \(i\)个盒子有 \(a_i\)个球。

依次进行以下 \(m\)次操作:

  • \(i\)次操作,将第 \(b_i\)个盒子的所有球均分,多余的球从第\(b_i + 1\)个盒子依次放一个。

问最后每个盒子的球数量。

解题思路

朴素做法为\(O(nm)\),考虑优化每次操作的复杂度。

注意到均分放一个都是区间加法,用线段树维护即可,时间复杂度是\(O(m\log n)\)

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

const int N = 5e5 + 10;

class segment {
#define lson (root << 1)
#define rson (root << 1 | 1)
  public:
    LL sum[N << 2];
    LL lazy[N << 2];

    void build(int root, int l, int r, vector<int>& a) {
        if (l == r) {
            sum[root] = a[l - 1];
            lazy[root] = 0;
            return;
        }
        int mid = (l + r) >> 1;
        build(lson, l, mid, a);
        build(rson, mid + 1, r, a);
        lazy[root] = 0;
    }

    void pushdown(int root) {
        if (lazy[root]) {
            sum[lson] += lazy[root];
            sum[rson] += lazy[root];
            lazy[lson] += lazy[root];
            lazy[rson] += lazy[root];
            lazy[root] = 0;
        }
    }

    void update(int root, int l, int r, int L, int R, LL val) {
        if (L <= l && r <= R) {
            sum[root] += val;
            lazy[root] += val;
            return;
        }
        pushdown(root);
        int mid = (l + r) >> 1;
        if (L <= mid)
            update(lson, l, mid, L, R, val);
        if (R > mid)
            update(rson, mid + 1, r, L, R, val);
    }

    LL query(int root, int l, int r, int pos) {
        if (l == r) {
            return sum[root];
        }
        pushdown(root);
        int mid = (l + r) >> 1;
        if (pos <= mid)
            return query(lson, l, mid, pos);
        else
            return query(rson, mid + 1, r, pos);
    }
} sg;

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;
    sg.build(1, 1, n, a);
    for (int i = 0; i < m; ++i) {
        int b;
        cin >> b;
        ++b;
        LL cnt = sg.query(1, 1, n, b);
        sg.update(1, 1, n, b, b, -cnt);
        LL div = cnt / n;
        if (div)
            sg.update(1, 1, n, 1, n, div);
        LL mo = cnt % n;
        if (mo) {
            if (b + mo <= n) {
                sg.update(1, 1, n, b + 1, b + mo, 1);
            } else {
                sg.update(1, 1, n, b + 1, n, 1);
                sg.update(1, 1, n, 1, mo - (n - b), 1);
            }
        }
    }
    for (int i = 1; i <= n; ++i) {
        cout << sg.query(1, 1, n, i) << " \n"[i == n];
    }

    return 0;
}



F - S = 1 (abc340 F)

题目大意

给定点\((x_0, y_0)\),求一整数点 \((a,b)\),使得 \((0,0), (a, b), (x_0,y_0)\) 形成的三角形的面积为\(1\)

解题思路

考虑将\((0,0) \to (x_0,y_0)\) 作为三角形的底,高的长度\(h\) 需满足\(\frac{1}{2} h \sqrt{x_0^2 + y_0^2} = 1\)

即将直线\((0,0) \to (x_0,y_0)\) 平移一下,距离其为\(h\)的直线即为 \((a,b)\)所处的位置。

直线 \((0,0) -> (x_0,y_0)\) 的直线方程为\(y_0 x - x_0 y = 0\)

根据两平行直线的方程,得\((a,b)\)所处的直线为 \(y_0 x - x_0 y + c = 0\)

根据俩平行直线距离公式,得其距离为\(\frac{|c|}{\sqrt{x_0^2 + y_0^2}}\),其为三角形的高 \(h\),代入上述公式得 \(|c| = 2\)

因此得到了 \((a,b)\)所处的直线方程为 \(y_0 x - x_0 y + 2 = 0\)以及\(y_0 x - x_0 y - 2 = 0\)

现在的问题就是找到一组整数解\((x,y)\),满足上述方程。

注意到上述即为一个不定方程,用扩展欧几里德解得即可。

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

template <typename T> T extgcd(T a, T b, T& x, T& y) {
    if (a == 0) {
        x = 0;
        y = 1;
        return b;
    }
    T p = b / a;
    T g = extgcd(b - p * a, a, y, x);
    x -= p * y;
    return g;
}

int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    LL a, b;
    cin >> a >> b;
    auto ok = [](LL a, LL b) {
        LL x, y;
        LL d = extgcd(b, a, x, y);
        if (2 % d != 0) {
            return false;
        }
        cout << x * 2 / d << ' ' << y * 2 / d << '\n';
        return true;
    };
    if (!ok(-a, b) && !ok(a, -b))
        cout << "-1\n";

    return 0;
}



G - Leaf Color (abc340 G)

题目大意

给定一棵树,点有颜色。

问子树的数量,其叶子颜色相同。

解题思路

<++>文章来源地址https://www.toymoban.com/news/detail-825347.html

神奇的代码



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

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

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

相关文章

  • Atcoder ABC340 C - Divide and Divide

    时间限制:2s 内存限制:1024MB 所有图片源自Atcoder,题目译文源自脚本Atcoder Better! 点击此处跳转至原题 【样例输入1】 【样例输出1】 【样例说明1】 【样例输入2】 【样例输出2】 【样例输入3】 【样例输出3】 老汉使用到的是记忆递归的解题方式 本题是求将 n 分解至 n 个 1

    2024年02月20日
    浏览(28)
  • AtCoder Beginner Contest 322

    给定一个字符串,找到最先出现 ABC 的位置。 直接查找判断即可。 神奇的代码 给定字符串 s 和 t ,问 s 是不是 t 的前缀和后缀。 根据前后缀定义判断即可。这里试了下 python 神奇的代码 (n) 天,有 (m) 天会放烟花。 问每一天,距离未来最近的放烟花的天数。 两个双指针一

    2024年02月08日
    浏览(21)
  • AtCoder Beginner Contest 336

    给定一个数 (n) ,将 long 中的 o 重复 (n) 次后输出。 模拟即可。 神奇的代码 给定一个数 (n) ,问 (n) 的二进制表示下的末尾零的数量。 即找到最小的 (i) 使得 (n (1 i)) 不为零的位置。枚举即可。 或者直接用内置函数 __builtin_ctz 。(count tail zero? 神奇的代码 定义一个数

    2024年01月20日
    浏览(32)
  • AtCoder Beginner Contest 326

    100楼层,一次可以上最多两层,或下最多三层。 给定两楼层,问能否一次到达。 比较大小,然后判断其差是是不是在 (2) 或 (3) 内即可。 神奇的代码 给定一个 (n) ,问不小于 (n) 的形如 (326) 的数字是多少。 形如 (326) 的数字,即数位有 (3) ,且百位 (times) 十位

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

    (n) 个人游戏,每局有一人 (+1) 分,有一人 (-1) 分。 给定最后前 (n-1) 个人的分数,问第 (n) 个人的分数。 零和游戏,所有人总分是 (0) ,因此最后一个人的分数就是前 (n-1) 个人的分数和的相反数。 神奇的代码 对于一个字符串,如果对于所有 (i geq 1) ,都有恰好

    2024年04月13日
    浏览(47)
  • AtCoder Beginner Contest 341

    给定 (n) ,输出 (n) 个 (0) 和 (n+1) 个 (1) 交替的字符串。 (101010...) 循环输出即可。 神奇的代码 货币兑换。 (A) 国货币每 (x_a) 钱可兑换 (B) 国货币 (y_a) 钱。 (B) 国货币每 (x_b) 钱可兑换 (C) 国货币 (y_b) 钱。 ... 给定你拥有的每国货币钱数和兑换规则,依次兑换

    2024年02月19日
    浏览(20)
  • AtCoder Beginner Contest 314

    怎么好多陌生单词 审核怎么这么逆天,半小时还没审完 给定 (pi) 的值以及数 (n) ,要求保留 (n) 位小数输出,不四舍五入。 字符串形式储存然后截取末尾即可。 神奇的代码 (n) 个人玩轮盘赌游戏,简单说就是一个转盘有 (37) 个数字以及一个箭头,箭头会等概率停在某

    2024年02月13日
    浏览(29)
  • AtCoder Beginner Contest 309

    感觉F写了个乱搞做法 给定一个 (3 times 3) 的网格,以及两个数字。 问这两个数字是否 水平相邻 。 求出两个数字的横纵坐标,看是否横坐标相同,纵坐标差一即可。 读题不仔细,开题就WA了。 神奇的代码 给定一个矩形。将最外围的数字顺时针旋转一格。 可以模拟一个指针

    2024年02月13日
    浏览(25)
  • AtCoder Beginner Contest 313

    貌似这次很难,还好去吃烧烤了 发现原来G就是个类欧几里德算法,参考abc283 ex,更了个G 给定 (n) 个数 (a_i) ,问第一个数要成为唯一的最大的数,应该加多少。 找到后面的最大的数 (m) ,答案就是 (max(0, m + 1 - a_0)) 。 神奇的代码 给定 (m) 条关于 (n) 个数的大小关系,

    2024年02月14日
    浏览(29)
  • AtCoder Beginner Contest 320

    给定 (a,b) ,输出 (a^b + b^a) 。 因为数不超过 (10) ,可以直接用 pow 计算然后转成 (int) 。不会有精度损失。 神奇的代码 给定一个字符串 (s) ,求长度最长的回文串。 因为长度只有 (100) ,可以直接枚举子串,然后暴力判断是不是回文串(翻转后是否和自身相同),复杂

    2024年02月08日
    浏览(27)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包